精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

Javascript基礎進階:面向對象和原型原型鏈

開發 前端
Javascript就是基于“面向對象”思想設計的編程語言,本篇給大家介紹Javascript基礎進階- 面向對象和原型原型鏈

[[347261]]

 * 學習進階方式 💪

基礎知識要夯實;

原理源碼要深入;

深度廣度要擴展;

簡短的概括:

1、面向對象理論知識總述

2、自定義類的創建和一些細節知識

3、面向對象中的原型和原型鏈

4、重寫內置new以及基于內置類原型擴展方法

5、THIS情況匯總及CALL、APPLY、BIND的應用

面向對象理論知識總述

* 核心答案 | 基礎知識要夯實

編程語言

1、OOP面向對象:

1)java,

2)python,

3)C++,

4)php,

5)C#(ASP.NET),

6)javascript -> Node.js

2、POP面向過程:

HTML和CSS是標記語言

1)less/sass/stylus:CSS預編譯語言,讓CSS具備面向對象編程的特點。

2)寫完的代碼無法被瀏覽器直接識別,需要編譯后(編譯成為正常的CSS)在瀏覽器中渲染。

什么是面向對象編程?

1、對象:泛指,萬物皆對象(JS中所有我們學習研究和開發的都是對象 「研究對象」);

2、類:對 “對象” 的一個細分,按照對應的功能特點,分成我們的大類和小類「類別」;

3、實例:某個類別中具體的事物;

* 關于類的“封裝、繼承、多態”

1)封裝:把實現某個功能的代碼封裝到函數中,起到“低耦合高內聚”的作用

2)繼承:子類及子類的實例繼承了父類中的屬性和方法

3)多態:函數的重載(方法名字相同,但是傳遞參數的個數或者類型不同,識別為兩個不同的方法 -> 后臺語言有這個特征,但是JS中不存在嚴格意義上的重載)和重寫(子類重寫父類的方法)

JS就是基于“面向對象”思想設計的編程語言

1、本身存在很多“內置類”

1)每一個數據類型都有一個自己所屬的內置類

2)獲取的元素集合或者節點集合也是有自己的類 HTMLCollection / NodeList

3)每一個元素標簽都有自己所屬的類

2、我們學習JS:拿出某個類的一個實例去研究和學習,當前實例研究明白后,那么當前實例所屬類下的其他實例,也具備這些特點... 

自定義類的創建和一些細節知識 

* 核心答案 | 基礎知識要夯實

自定義類(所有的類「內置類/自定義類」都是“函數數據類型”的值)

函數執行的時候基于new執行即可 “構造函數執行”。

🌰 例如一:普通函數 與 構造函數

  1. function Fn(x, y) { 
  2.     let total = x + y; 
  3.     this.x = x; 
  4.     this.y = y; 
  5.     return total; 
  6. // 1、作為普通函數執行 
  7. Fn(10, 20); 
  8.  
  9. // 2、構造函數執行 
  10. // 說明:f1是Fn這個類的一個實例對象 
  11. let f1 = new Fn(10, 20); 
  12. console.log(f1.x, f1.y, f1.total);  
  13. // 說明:total只是上下文中的私有變量,和實例f1沒有關系」 
  14. // 結果:10 20 undefined 

畫圖分析:( 有圖有真相 )

構造函數 VS 普通函數

1、構造函數執行,最開始會像普通函數執行一樣,形成私有的上下文。

1)AO;

2) SCOPE-CHAIN;

3)形參賦值;

4)變量提升;

5)代碼執行;

不同的地方:

1、創建上下文之后,瀏覽器默認幫助我們創建一個對象 “實例對象”。

1)把當前Fn函數當作一個類“構造函數”

2)創建的對象就是這個類的一個實例

2、初始this的時候,讓this指向當前創建的實例對象。

3、在代碼執行完,返回值的時候

1)如果函數沒有寫return,或者返回的是一個基本數據類型值,則瀏覽器默認,會把創建的實例對象返回;

2)如果函數本身返回的就是一個引用數據類型值,還是以自己返回的為主。

🌰 例如二:構造函數擴展

  1. function Fn(x, y) { 
  2.     let total = x + y; 
  3.     this.x = x; 
  4.     this.y = y; 
  5.     return { 
  6.         name'前端學苑' 
  7.     }; 

說明:

由于構造函數體中,默認自己返回一個引用類型值,所以f1不再是創建的Fn實例,而是自己返回的對象。

let f1 = new Fn(10, 20);

“實例 instanceof 構造函數” :檢測當前實例是否屬于這個類。

console.log(f1 instanceof Fn); //false

🌰 例如三:函數擴展

  1. function Fn(x, y) { 
  2.     let total = x + y; 
  3.     this.x = x; 
  4.     this.y = y; 
  5.     this.say = function say() { 
  6.         console.log(`SAY:${total}`); 
  7.     }; 
  8. let f1 = new Fn(10, 20); 
  9. let f2 = new Fn; 

畫圖分析:( 有圖有真相 )

結果:

  1. console.log(f1 === f2); //false 
  2. console.log(f1.say === f2.say); //false 

Fn VS Fn()

1) Fn代表的是函數本身(堆內存 -> ƒ Fn(x, y) {...});

2) Fn()是把函數執行,獲取其返回值; 

new Fn VS new Fn()

都是把Fn執行了,只是第一個沒有傳遞實參,第二個可以傳遞實參而已。

1) new Fn; 運算優先級是18(無參數列表new)

2) new Fn(); 運算符優先級是19(有參數列表new)

* 檢測一個屬性是否為當前對象的成員

1)屬性名 in 對象:不論是私有屬性還是公有的屬性,只要有就是true;

2)對象.hasOwnProperty(屬性名):必須是對象的私有屬性,結果才是true;

說明:自己擴展一個方法 hasPubProperty(對象,屬性名):檢測當前屬性是否屬于對象的公有屬性(特點:必須有這個屬性,而且不是私有的)(需要擴展)

屬性和變量有什么共同點:

沒有。屬性是堆內存的成員,變量是棧內存或者上下文當中變量。

  1. console.log('say' in f1); //true 
  2. console.log('toString' in f1); //true 
  3. console.log('total' in f1); //false 
  4. console.log(f1.hasOwnProperty('say')); //true 
  5. console.log(f1.hasOwnProperty('toString')); //false 
  6. console.log(f1.hasOwnProperty('total')); //false 

🌰 例如四:函數擴展

  1. Object.prototype.AA = '前端學苑'
  2. let obj = { 
  3.     name'xxx'
  4.     age: 11, 
  5.     0: 100, 
  6.     [Symbol('AA')]: 200, 
  7.     [Symbol.toPrimitive]: function () { 
  8.         return 0; 
  9.     } 
  10. }; 

基于“for...in”循環遍歷對象

1) 優先遍歷數字屬性;

2) 不會遍歷到Symbol屬性;

3) 會把自己擴展到“類原型”上的公共屬性方法也遍歷到「可枚舉的」

  1. for (let key in obj) { 
  2.     // 在遍歷過程中,遍歷到公共屬性,則停止遍歷: 
  3.     // 因為for...in遍歷的本意就是只遍歷私有的屬性即可 
  4.     if (!obj.hasOwnProperty(key)) break; 
  5.     console.log(key); 

  1. let keys = [ 
  2.     ...Object.keys(obj), 
  3.     ...Object.getOwnPropertySymbols(obj) 
  4. ]; 
  5. keys.forEach(key => { 
  6.     console.log(`屬性名:${String(key)},屬性值:${obj[key]}`); 
  7. });  

說明:

1)Object.keys(obj):獲取當前對象所有非Symbol的私有屬性「數組」 =>Object.getOwnPropertyNames. 

2)Object.getOwnPropertySymbols(obj):獲取對象所有的Symbol私有屬性「數組」.

面向對象中的原型和原型鏈 

* 核心答案 | 基礎知識要夯實

1、函數數據類型

1)普通函數

2)箭頭函數

3)生成器函數

4)構造函數(類)

2、對象數據類型

1)普通對象/數組對象/正則對象/日期對象...

2)實例也是對象數據類型的(排除7種原始值類型)

3)prototype/__proto__原型屬性值也是對象(排除Function.prototype)

3、大部分函數(重點是構造函數) 都內置一個prototype(原型「顯式原型」)的屬性,屬性值是一個對象,對象中存儲的屬性和方法,是供當前類所屬實例,調用的“公共”的屬性和方法

1)箭頭函數是沒有prototype屬性的;

2)在原型對象上有一個內置的屬性 constructor(構造器),屬性值是當前函數本身;

4、每一個對象都內置一個__proto__(原型鏈「隱式原型」)的屬性,屬性值指向自己所屬類的原型prototype對象。

1)Object.prototype這個對象的__proto__值是null,因為Object是所有對象的“基類”

只繪制“堆內存”,畫圖分析:( 有圖有真相 )

解析說明:

每一個數組都是Array類的實例,所以每一個數組的_proto_一定指向Array.prototype; 

每一個對象都是Object類的實例,所以Array.prototype對象中的_proto_屬性指向Object.prototype; 

原型鏈的查找機制

arr[1]或者 arr.push() 再或者 arr.hasOwnProperty()…

1)首先查找當前實例對象的私有屬性,私有中有,獲取就是私有的;

2)如果私有中沒有,則瀏覽器默認基于_proto_找其所屬類原型(prototype)上的公共屬性和方法;

3)如果還找不到,則基于原型對象上的_proto_繼續向上查找 … 直到找到Object.prototype為止。最終到null。

例如:arr.push <=> arr._proto_.push <=> Array.prototype.push

1)找到的方法都是相同的;

2)區別是方法執行時候,里面的this 不同;

(1)arr.push() arr首先基于原型鏈查找機制,找到Array.prototype上的push 方法,并且把方法執行,方法中的this -> arr;

(2)arr._proto_.push() 直接跳過私有屬性的查找,找公共的,方法執行的時候,方法中的this -> arr._proto_;

Array.prototype.push() this -> Array.prototype

3)_proto_ 在IE瀏覽器中進行訪問。(那如果代碼需要用到_proto_ ,怎么在IE中用呢? 結果:不能用。) 

arr.hasOwnProperty('push') -> false

Array.prototype.hasOwnProperty('push') -> true

公有還是私有屬性,它是有參照物的

1)存儲在自己的堆內存中的屬性是 “私有的”;

2)基于_proto_查找到的屬性和方法有“公有的”;

每一個數組“即是數組也是對象”,因為它們可以調用Array.prototype和Object.prototype的屬性和方法。
* 構造函數、原型與實例之間的關系

關系解析說明:

每個構造函數都有一個prototype屬性指向它的原型對象,原型對象的constructor 指向構造函數,通過new 構造函數 生成實例,實例的__proto__屬性指向原型對象。

🌰 原型與原型鏈

  1. function Fn() { 
  2.     this.x = 100; 
  3.     this.y = 200; 
  4.     this.getX = function () { 
  5.         console.log(this.x); 
  6.     } 
  7. Fn.prototype.getX = function () { 
  8.     console.log(this.x); 
  9. }; 
  10. Fn.prototype.getY = function () { 
  11.     console.log(this.y); 
  12. }; 
  13. let f1 = new Fn; 
  14. let f2 = new Fn; 
  15. console.log(f1.getX === f2.getX); // false 「都是私有的方法」 
  16. console.log(f1.getY === f2.getY); // true 「都是公共的方法」 
  17. console.log(f1.__proto__.getY === Fn.prototype.getY); // true 
  18. console.log(f1.__proto__.getX === f2.getX); // false 
  19. console.log(f1.getX === Fn.prototype.getX); // false 
  20. console.log(f1.constructor);  // fn 
  21. console.log(Fn.prototype.__proto__.constructor); // Object 
  22. f1.getX(); 
  23. f1.__proto__.getX(); 
  24. f2.getY(); 
  25. Fn.prototype.getY(); 

畫圖分析:( 有圖有真相 )

解析說明:

1)先確定執行哪個方法「私有|公有」;

2)再確定執行方法中的this;

3)最后方法執行,計算機需要的結果即可; 

f1.getX()

執行的私有方法,this -> f1

console.log(f1.x) => 100

f1._proto_.getX()

執行的公有方法,this -> f1._proto_

console.log(f1._proto_.x) => undefined

f2.getY()

執行的公有方法,this -> f2

console.log(f2.y) => 200

Fn.prototype.getY()

執行的公有方法,this -> Fn.prototype

console.log(Fn.prototype.y) => undefined

重寫內置new以及基于內置類原型擴展方法 

* 核心答案 | 基礎知識要夯實

🌰 * 1、new執行的原理 - 面試題( 面試常問 )

  1. function Dog(name) { 
  2.     this.name = name
  3. Dog.prototype.bark = function () { 
  4.     console.log('wangwang'); 
  5. Dog.prototype.sayName = function () { 
  6.     console.log('my name is ' + this.name); 
  7. /* 
  8. let sanmao = new Dog('三毛'); 
  9. sanmao.sayName(); 
  10. sanmao.bark(); 
  11. */ 
  12. function _new() { 
  13.     //=>完成你的代碼    
  14. let sanmao = _new(Dog, '三毛'); 
  15. sanmao.bark(); //=>"wangwang" 
  16. sanmao.sayName(); //=>"my name is 三毛" 
  17. console.log(sanmao instanceof Dog); //=>true 

解決方法一( __proto__ 在IE瀏覽器兼容很差,不建議使用 )

  1. function _new(Ctor, ...params) { 
  2.     // Ctor->Dog params->['三毛'
  3.     let obj = {}; 
  4.     obj.__proto__ = Ctor.prototype; 
  5.     // this->指向創建的實例對象  基于call方法改變即可 
  6.     let result = Ctor.call(obj, ...params); 
  7.     if (/^(object|function)$/.test(typeof result)) return result; 
  8.     return obj; 
  9. }  

解析說明:

1、創建一個實例對象 實例對象.__proto__===所屬類.prototype;

2、會把構造函數當做普通函數執行「私有上下文、作用域鏈、初始THIS、形參賦值...」;

3、觀察函數執行的返回值,如果沒有返回值或者返回的是基本數據類型值,默認返回的都是實例對象,否則以自己返回的值為主。

Object.create([pro]):創建一個空對象,把[pro]作為當前創建空對象的__proto__的指向(把[pro]作為當前創建空對象的原型)。

1、[pro]可以傳遞null或者一個對象;

2、如果傳遞的是null,則當前空對象不具備__proto__的屬性,也就是不屬于任何類的實例。

🌰 例如:

  1. let pro = { 
  2.     A: 10, 
  3.     B: 20 
  4. }; 
  5. //Uncaught TypeError: Object prototype may only be an Object or null: undefined 
  6. console.log(Object.create());  
  7. console.log(Object.create(null)); 

解決方法二( 在IE6,7,8瀏覽器不兼容 )

  1. function _new(Ctor, ...params) { 
  2.     let obj = Object.create(Ctor.prototype); 
  3.     let result = Ctor.call(obj, ...params); 
  4.     if (/^(object|function)$/.test(typeof result)) return result; 
  5.     return obj; 
  6. }  

解決方法三 ( 兼容性比較好 )

  1. // 重寫的方法只考慮pro傳遞的是一個對象 
  2. Object.create = function (pro) { 
  3.     function Proxy() {} 
  4.     Proxy.prototype = pro; 
  5.     return new Proxy; 
  6. }; 
  7.  
  8. function _new(Ctor) { 
  9.     // 獲取除第一個實參以外,剩余傳遞的參數信息,以數組的形式保存到params中 
  10.     var params = [].slice.call(arguments, 1); 
  11.     // Object.create兼容IE低版本瀏覽器,需要改寫 
  12.     var obj = Object.create(Ctor.prototype); 
  13.     // 基于apply既可以改變this,也可以把數組中的每一項傳遞給函數 
  14.     var result = Ctor.apply(obj, params); 
  15.     if (/^(object|function)$/.test(typeof result)) return result; 
  16.     return obj; 

* 2、擴展內置類原型上的方法

1、調用的時候更加方便;

2、也更好的實現鏈式調用;

* 注意:自己編寫的方法會覆蓋內置的方法,所以自己命名的時候需要注意,一般都是設置前綴,例如:myUnique。

🌰 常用數組去重方法

  1. function unique(arr) { 
  2.     // 首先基于Set結構去重,最后轉換為數組 
  3.     let result = new Set(arr); 
  4.     result = Array.from(result); 
  5.     return result; 
  6. let arr = [1, 2, 3, 2, 3, 4, 2, 3, 4, 2, 1, 2, 3, 4, 5, 3, 4]; 
  7. let result = unique(arr); 
  8. console.log(result);  

🌰 先去重,再排序 - 面試題( 面試常問 )

  1. Array.prototype.unique = function unique() { 
  2.     // this->arr 一般是當前操作類的實例 
  3.     let result = new Set(this); 
  4.     result = Array.from(result); 
  5.     return result; //返回的結果還是一個數組,則可以繼續調用數組的其它方法 ->“鏈式調用” 
  6. }; 
  1. // 先去重,再排序 
  2. //  + sort是Array.prototype上的方法,所以數組可以直接調用 
  3. let arr = [1, 2, 3, 2, 3, 4, 2, 3, 4, 2, 1, 2, 3, 4, 5, 3, 4]; 
  4. let result = arr.unique().sort((a, b) => a - b); 
  5. console.log(arr, result); 

THIS情況匯總及CALL、APPLY、BIND的應用 

* 核心答案 | 基礎知識要夯實

1、THIS的幾種情況

1)事件綁定;

2)函數執行:1)自執行函數 2)回調函數;

3)構造函數執行;

4)基于call /apply /bind 改變函數中的this;

5)箭頭函數中沒有自己的this,所用到的this是使用其上下文中的;

說明:Function.prototype -> call/apply/bind 所有的函數都可以調取這三個辦法。

  1. Function.prototype.call = function call(context) { 
  2.     // this->fn 
  3.     // context->obj 
  4.     // ... 
  5. };  

🌰 基于call /apply /bind 改變函數中的this

  1. window.name = 'WINDOW'
  2. let obj = { 
  3.     name'前端學苑'
  4.     age: 2 
  5. }; 
  6.  
  7. function fn(x, y) { 
  8.     console.log(this, x + y); 
  9. }  
  10.  
  11. fn(); //this->window 
  12. obj.fn(); //Uncaught TypeError: obj.fn is not a function 
  1. fn.call(obj); //this->obj   
  2. fn.call(obj, 10, 20); //this->obj x->10 y->20 
  3. fn.call(); //this->window 嚴格模式下undefined 
  4. fn.call(null); //this->window 嚴格模式下null 「傳遞的是undefiend也是如此」 
  5. fn.call(10, 20); //this->10「對象」 x->20  y->undefined 

解析說明:

fn.call(obj);

底層處理方式:fn先基于__proto__找到Function.prototype.call,把call方法執行的時候,call方法內部實現了一些功能:會把fn執行,并且讓fn中的this變為第一個實參值。

* apply的作用和細節上和call一樣,只有一個區別:傳遞給函數實參的方式不一樣。

  1. fn.call(obj, 10, 20); 
  2. fn.apply(obj, [10, 20]);  

最后結果和call是一樣的,只不過apply方法執行的時候要求:傳遞給函數的實參信息都要放置在一個數組中,但是apply內部也會向call方法一樣,把這些實參信息一項項的傳遞給函數。

🌰 需求:獲取數組中的最大值

  1. let arr = [10, 30, 15, 36, 23]; 

* 方法一:先排序

  1. arr.sort(function (a, b) { 
  2.     return b - a; 
  3. }); 
  4. let max = arr[0]; 
  5. console.log('數組中的最大值是:' + max);  

* 方法二:假設法

第一種方法:

  1. let max = arr[0]; 
  2. for (let i = 1; i < arr.length; i++) { 
  3.     let item = arr[i]; 
  4.     if (item > max) { 
  5.         max = item; 
  6.     } 
  7. console.log('數組中的最大值是:' + max);  

第二種方法:

  1. let max = arr.reduce((result, item) => { 
  2.     return item > result ? item : result; 
  3. }); 
  4. console.log('數組中的最大值是:' + max); 

* 方法三:借用Math.max

第一種方法:

  1. Math.max(10, 30, 15, 36, 23) ->36 獲取一堆數中的最大值 
  2. Math.max([10, 30, 15, 36, 23]) ->NaN 傳遞一個數組是不行的 

第二種方法:ES6展開運算符

  1. let max = Math.max(...arr); 
  2. console.log('數組中的最大值是:' + max); 

第三種方法:基于apply的特點

  1. let max = Math.max.apply(null, arr); 
  2. console.log('數組中的最大值是:' + max); 

第四種方法:字符串拼接成為最終想要的表達式

  1. let str = `Math.max(${arr})`; 
  2. let max = eval(str); 
  3. console.log('數組中的最大值是:' + max); 

🌰 需求:把類數組集合轉換為數組集合

重寫內置的slice,實現淺克隆;

  1. Array.prototype.slice = function slice() { 
  2.     // 重寫內置的slice,實現淺克隆 
  3.     // this->ary 
  4.     let arr = []; 
  5.     for (let i = 0; i < this.length; i++) { 
  6.         let item = this[i]; 
  7.         arr.push(item); 
  8.     } 
  9.     return arr; 
  10. }; 
  11. let ary = [10, 20, 30]; 
  12. let newAry = ary.slice(); //不傳遞或者傳遞0 -> 數組的淺克隆 
  13. console.log(newAry, newAry === ary);  

畫圖分析:( 有圖有真相 )

區別在于:

1、內置代碼中用的是this,自己寫的代碼中用的是argument。

2、如果我們可以 讓內置的slice執行,并且把方法中的 this改變為arguments -> 這樣其實就是把類數組集合克?。ㄞD換)為數組。

3、讓內置slice執行:找到slice,加小括號一執行即可。

1)Array.prototype.slice() 2)[].slice()

改變方法中的this

1)call 2)apply 

4、[].slice.call(arguments) 把類數組轉換為數組

重要:數組中大部分方法,都可以基于這樣的原理(改變this),實現類數組的借用。原因:類數組除了不是Array的實例,和數組的結果是一致的,所以操作數組的一些代碼(類似于循環等操作)也一定適用于類數組,所以可以實現方法的借用。

求和第一種方法:

  1. function sum() { 
  2.     // arguments:實參集合,它是一個類數組,不是Array的實例,所以不能直接調用Array.prototype上的方法,但是結構和數組非常的相似,都是索引+length 
  3.     // 第一種方法 
  4.     let arr = []; 
  5.     for (let i = 0; i < arguments.length; i++) { 
  6.         let item = arguments[i]; 
  7.         arr.push(item); 
  8.     } 
  9.     // 第二種方法 
  10.     // let arr = [].slice.call(arguments); 
  11.     return arr.reduce((result, item) => item + result); 
  12. }  
  13. let total = sum(10, 20, 30, 40); 

求和第二種方法,ES6實現:

  1. function sum(...arr) { 
  2.     // 第一種方法:... arr 基于剩余運算符獲取的實參集合本身就是一個數組 
  3.      
  4.     // 第二種方法:Array.from:可以把一個類數組(或者Set)轉換為數組 
  5.     // let arr = Array.from(arguments); 
  6.  
  7.     // 第三種方法:基于展開運算符把類數組中的每一項拿出來,分別賦值給數組 
  8.     // let arr = [...arguments]; 
  9.     return arr.reduce((result, item) => item + result); 
  10.  
  11. let total = sum(10, 20, 30, 40); 
  12. console.log(total);   // 結果:100 

🌰 this指向的例子

  1. let obj = { 
  2.     name'前端學苑'
  3.     age: 11 
  4. }; 
  5.  
  6. function fn(x, y) { 
  7.     console.log(this, x, y); 
  8. }  

1、操作一:

  1. document.body.onclick = fn; 

分析:

1)事件綁定的時候方法是沒有執行的,只有事件觸發,瀏覽器會幫助我們把方法執行;

2)this->body;

3)x->MouseEvent 事件對象「瀏覽器不僅幫助我們把方法執行,而且還把存儲當前操作的信息的事件對象傳遞給函數」;

4)y->undefined;

2、操作二:

  1. setTimeout(fn, 1000); 

分析: 

1)設置一個定時器(此時綁定的函數沒有執行,此時只是綁定一個方法),1000MS后,瀏覽器會幫助我們把fn執行;

2)this->window;

3)x->undefined;

4)y->undefined;

我們期望:不論是事件觸發,還是定時器到時間,執行對應的方法時,可以改變方法中的this,以及給方法傳遞實參信息。

1、“立即處理的思想”

直接下屬這種操作辦法是不可以的:call/apply在處理的時候,會把函數立即執行,也就是在事件綁定或者設置定時器的時候,fn就執行了,而不是等待事件觸發或者定時器到時間后再執行 “立即處理的思想”。

代碼如下:

  1. document.body.onclick = fn.call(obj, 10, 20); 
  2. setTimeout(fn.call(obj, 10, 20), 1000); 

2、“預先處理思想「柯理化函數」”

我們綁定方法的時候(不論是事件綁定還是設置定時器),先綁定一個匿名函數,事件觸發或者達到時間,先把匿名函數執行,在執行匿名函數的時候,再把我們需要執行的fn執行,此時就可以基于call/apply改變this和參數信息了。

代碼如下:

  1. document.body.onclick = function (ev) { 
  2.     //this->body 
  3.     fn.call(obj, 10, 20, ev); 
  4. }; 
  5. setTimeout(function () { 
  6.     //this->window 
  7.     fn.call(obj, 10, 20); 
  8. }, 1000);  

bind相當于call/apply來講,并不會把函數立即執行,只是實現處理了要改變的this和參數,一切的執行還是按照原有的時間或者觸發節點進行。

代碼如下:

  1. document.body.onclick = fn.bind(obj, 10, 20); 
  2. setTimeout(fn.bind(obj, 10, 20), 1000); 

* 箭頭函數沒有自己的this

🌰 實例一:

  1. let obj = { 
  2.     name'前端學苑'
  3.     age: 11, 
  4.     fn: function () { 
  5.         // this->obj 
  6.         let that = this; 
  7.         return function () { 
  8.             // this->window 
  9.             // 如果需要改變obj.name,可以用that替換this 
  10.             that.name = 'FE2020'
  11.             console.log(this); 
  12.         }; 
  13.     } 
  14. }; 
  15. let f = obj.fn(); 
  16. f(); 

🌰 實例二:

  1. let obj = { 
  2.     name'前端學苑'
  3.     age: 11, 
  4.     fn: function () { 
  5.         // this->obj 
  6.         return () => { 
  7.             this.name = 'FE2020'
  8.             console.log(this); // {name:'FE2020', age: 11, fn:f} 
  9.         }; 
  10.     } 
  11. }; 
  12. let f = obj.fn(); 
  13. f.call(100);  

說明:

箭頭函數沒有this(方法執行的時候不存在初始this這一項操作),所以基于call/apply操作它都是無用的,沒有this。

責任編輯:姜華 來源: 前端學苑
相關推薦

2019-02-27 16:00:48

JS原型原型鏈對象

2020-02-20 14:00:15

JavaScript原型原型鏈

2010-10-08 09:13:15

oop模式JavaScript

2012-11-08 10:40:47

JavaScript原型鏈

2023-08-28 07:12:54

2017-04-07 11:15:49

原型鏈原型Javascript

2017-05-05 10:31:35

JavaScriptprototype__proto__

2012-01-05 15:07:11

JavaScript

2012-12-13 11:01:42

IBMdW

2016-06-07 14:28:39

Javascript原型

2022-05-26 09:20:01

JavaScript原型原型鏈

2020-09-10 07:04:30

JSJavaScript 原型鏈

2022-03-29 09:15:55

Javascript函數屬性

2022-05-26 23:14:26

原型原型鏈JS繼承

2011-08-24 13:51:56

JavaScript

2024-08-09 12:44:45

JavaScript原型鏈鏈條

2016-05-06 14:02:18

JavaScript原型鏈

2016-12-27 09:10:29

JavaScript原型鏈繼承

2011-08-31 14:48:33

JavaScript

2015-06-09 10:55:58

JavaScriptinstanceof運
點贊
收藏

51CTO技術棧公眾號

日本高清无吗v一区| 成人av免费在线| 久久精品国产一区| 亚洲熟女乱综合一区二区| 欧美日韩经典丝袜| av亚洲精华国产精华精| 国产精品高潮呻吟久久av野狼 | 99久久婷婷国产综合精品| 91av在线网站| 三级黄色在线观看| 日韩中出av| 精品一区二区国语对白| 欧美成年人视频| 女人被狂躁c到高潮| 久久99久久久精品欧美| 亚洲成年人影院| 亚洲欧美影院| 手机看片1024日韩| 麻豆91小视频| 欧美性做爰毛片| 91视频综合网| 精品国产欧美日韩| 亚洲国产成人av在线| 亚洲一级片网站| 三级视频网站在线| 韩国女主播成人在线观看| 992tv成人免费视频| 亚洲一级生活片| 国产一区二区观看| 亚洲激情视频在线| 人妻巨大乳一二三区| 粉嫩91精品久久久久久久99蜜桃| 亚洲福利国产精品| 熟妇熟女乱妇乱女网站| 国产高清美女一级毛片久久| 久久精品卡一| 欧美高清在线播放| 在线日韩国产网站| 精品美女视频| 亚洲男人天堂2024| caopor在线视频| av电影免费在线看| 91在线一区二区| 91成人免费视频| 中文字幕一区二区在线视频 | 亚洲国产精品久久久久婷蜜芽| 成人在线观看免费网站| 国产精品久久三| 欧美自拍资源在线| 正在播放亚洲精品| 久久国产毛片| 欧美中文字幕视频| 尤物视频在线观看国产| 亚洲大片在线| 久久久久久久久电影| 国产精品成人免费观看| 亚洲精品成人| 久久97久久97精品免视看| 2025国产精品自拍| 亚洲天天综合| 欧美片一区二区三区| 黑鬼狂亚洲人videos| 午夜欧美在线| 欧美大胆a视频| 欧美成人三级视频| 黄色精品一区| 久久免费国产视频| 奇米影视第四色777| 最新亚洲视频| 热久久这里只有精品| 亚洲影院在线播放| 日韩国产欧美在线视频| 国产精品第3页| 一区二区久久精品66国产精品| 美女看a上一区| 国产精品无码专区在线观看| 久久久久久久久久久久久久久久久 | 久久成人亚洲| 国产精品稀缺呦系列在线| 亚洲最大成人在线视频| 国产一区二区三区黄视频 | 欧美日韩在线视频播放| 日韩电影在线看| 成人精品一区二区三区电影免费| 国产suv精品一区二区69| 国产成a人亚洲| 久久伊人一区二区| 中文字幕在线免费| 一区二区不卡在线视频 午夜欧美不卡在 | 草草草视频在线观看| 欧美少妇另类| 中文字幕欧美国产| 免费极品av一视觉盛宴| 老色鬼在线视频| 欧美日韩久久一区| 成年女人免费视频| 精品欧美激情在线观看| 欧美成人午夜激情在线| 日本特级黄色片| 国产在线精品一区二区夜色| 国产精品亚洲不卡a| 国产小视频免费在线网址| 亚洲欧美区自拍先锋| 久久综合色视频| 日本动漫同人动漫在线观看| 精品国产鲁一鲁一区二区张丽| 免费一级特黄录像| 亚洲开心激情| 中文一区二区视频| 国产成人在线播放视频| 国产一区激情在线| 日本一区高清在线视频| 羞羞的视频在线观看| 在线观看视频一区| 水蜜桃av无码| 亚洲五月综合| 国产精品久久激情| 天天射天天操天天干| 综合网在线视频| 色中文字幕在线观看| aaa在线播放视频| 91麻豆精品91久久久久久清纯| 亚洲午夜久久久久久久久红桃 | 国产日韩一区二区三区在线| 国产在线观看不卡| 免费国产在线观看| 午夜a成v人精品| 国产探花一区二区三区| 久久亚洲在线| 国产精品免费福利| 青春草在线观看| 亚洲成人在线观看视频| 捷克做爰xxxⅹ性视频| 精品久久91| 欧美洲成人男女午夜视频| 亚洲美女性生活| 亚洲免费观看在线视频| 三级一区二区三区| 日韩在线观看一区 | 中文精品视频一区二区在线观看| 中文在线资源| 日韩精品极品毛片系列视频| 九九热视频精品| 国产精品一卡二| 国产精品高清一区二区三区| 老司机午夜在线视频| 91久久香蕉国产日韩欧美9色| 内射中出日韩无国产剧情| 亚洲看片免费| 久久国产精品一区二区三区四区| 黄页网站在线观看免费| 精品美女一区二区| 疯狂揉花蒂控制高潮h| 激情欧美一区二区三区| 国产99在线免费| 日本在线视频网址| 精品国产一区二区三区忘忧草 | 巨骚激情综合| 在线观看国产精品网站| 成人免费无遮挡无码黄漫视频| 亚洲中午字幕| 欧美亚洲免费高清在线观看 | 91丝袜美腿高跟国产极品老师| 丰满少妇久久久| 欧美黑人做爰爽爽爽| 97人人爽人人喊人人模波多| 天天综合网在线观看| 黑人巨大精品欧美一区二区免费| 网站一区二区三区| 亚洲精品一二三**| 久久久爽爽爽美女图片| 男人天堂网在线视频| 午夜成人免费视频| 午夜在线观看一区| 久久av资源站| 成人免费在线视频播放| 欧美日韩一本| 国产精品欧美激情| www.在线视频| 亚洲精品av在线| 国产精品suv一区| 国产精品日韩成人| 亚洲AV无码久久精品国产一区| 伊人久久成人| 日韩影视精品| 视频在线观看免费影院欧美meiju| 久久人91精品久久久久久不卡 | 国产亚洲精品高潮| 国产精品国产精品国产专区| 亚洲午夜日本在线观看| 国产 欧美 在线| 国产自产v一区二区三区c| 亚洲国产精品无码观看久久| 一区二区美女| 亚洲一区二区三区成人在线视频精品 | 亚洲少妇在线| 涩涩涩999| 国产福利一区二区精品秒拍| 国产精品jvid在线观看蜜臀 | 久久人人看视频| 1024国产在线| 日韩激情视频在线| 国产欧美综合视频| 色婷婷亚洲精品| 国产亚洲精品成人| 国产精品美女久久久久久久久| 亚洲国产精品第一页| 美洲天堂一区二卡三卡四卡视频| 欧美这里只有精品| 欧美肉体xxxx裸体137大胆| 7777精品久久久大香线蕉小说| 欧洲亚洲两性| 久久久亚洲欧洲日产国码aⅴ| 中文字幕在线观看日本| 亚洲精品影视在线观看| 亚洲精品福利网站| 欧美老人xxxx18| 久久亚洲精品石原莉奈 | 小泽玛利亚av在线| 国际精品欧美精品| 精品国产一区二区三| av在线理伦电影| 中文字幕在线看视频国产欧美| 日韩一级片免费看| 日韩一区二区三区四区| 亚洲中文一区二区三区| 日韩欧美在线播放| 日本精品在线观看视频| 免费在线视频一区| 三上悠亚久久精品| 欧美精品二区| 精品欧美国产| 在线一区二区三区视频| 成人福利网站在线观看| 欧美精品总汇| 久久久91精品国产一区不卡| 免费黄色片在线观看| 亚洲黄色av女优在线观看| 精品国产亚洲一区二区麻豆| 欧美日韩国产三级| 中文字幕777| 欧美在线观看视频一区二区| 无码人妻精品一区二| 欧美日韩一区二区精品| 日产欧产va高清| 亚洲一二三四在线观看| 麻豆一区二区三区精品视频| 亚洲免费高清视频在线| 色婷婷在线视频观看| 亚洲女同一区二区| 欧美成人三级视频| 亚洲一二三四在线观看| 国产在线观看你懂的| 亚洲午夜三级在线| 在线观看国产亚洲| 欧美日韩在线视频一区| 中文字幕在线播| 色美美综合视频| 欧美高清69hd| 欧美日韩电影在线| 国产又粗又猛又色又| 日韩一区二区三区四区五区六区| 精品人妻午夜一区二区三区四区 | 一区二区三区中文字幕在线观看| 国内偷拍精品视频| 婷婷开心久久网| 国产精品免费精品一区| 欧洲av一区二区嗯嗯嗯啊| 伊人久久亚洲综合| 欧美一级在线视频| 成人久久精品人妻一区二区三区| 亚洲国产天堂网精品网站| 青青草免费观看免费视频在线| 亚洲欧美制服综合另类| 香蕉视频国产在线观看| 萌白酱国产一区二区| 国产后进白嫩翘臀在线观看视频 | 日本三级视频在线| 一本色道a无线码一区v| 中文字幕永久在线视频| 日韩欧美国产精品一区| 日韩中文字幕观看| 亚洲午夜av久久乱码| 麻豆最新免费在线视频| 久久久久五月天| 欧美va视频| 91综合免费在线| 日韩免费电影在线观看| 一区一区视频| 亚洲三级视频| 三级一区二区三区| 99在线精品观看| a一级免费视频| 午夜视频在线观看一区二区 | 欧美日韩国产在线播放网站| 国模无码一区二区三区| 亚洲欧美国产日韩天堂区| 国产黄网站在线观看| 欧美中文字幕视频在线观看| а天堂中文最新一区二区三区| 欧洲美女7788成人免费视频| 国产成人精品一区二区三区视频| 99理论电影网| 成人嘿咻视频免费看| 日本香蕉视频在线观看| 日本美女一区二区三区| 人妻熟妇乱又伦精品视频| 麻豆专区一区二区三区四区五区| 欧美极品jizzhd欧美仙踪林| 欧美激情一区二区三区| 日本熟妇一区二区| 欧美肥胖老妇做爰| 国产永久免费高清在线观看 | 亚洲二区三区不卡| 六月丁香婷婷激情| 国产凹凸在线观看一区二区| ass极品国模人体欣赏| 精品久久久久久久久久国产| 国产美女明星三级做爰| 中文日韩电影网站| 国产精欧美一区二区三区蓝颜男同| 亚洲xxx大片| 久久国产成人精品| 女人扒开屁股爽桶30分钟| 成人性生交大合| 国产免费美女视频| 欧美性videosxxxxx| 欧美女子与性| 456国产精品| 99精品在免费线中文字幕网站一区| 咪咪色在线视频| 久久99精品久久久久| 国产一二三av| 欧美亚洲愉拍一区二区| 免费一级在线观看| 热99精品只有里视频精品| 人妖一区二区三区| 黄页免费在线观看视频| 成人天堂资源www在线| 欧美日韩免费一区二区| 欧美一区二区在线看| 黄网站在线免费| 国产精选久久久久久| 欧美手机在线| 成人性生生活性生交12| 国产日韩欧美精品一区| 免费看特级毛片| 欧美日韩国产成人在线91| 最新真实国产在线视频| 91精品国产综合久久久久久蜜臀| 成人影视亚洲图片在线| 色综合天天色综合| 国产精品日韩成人| 国产又大又粗又长| 欧美美最猛性xxxxxx| 综合欧美亚洲| 欧美视频免费看欧美视频| 99国产一区二区三精品乱码| 日韩欧美激情视频| 精品视频在线播放色网色视频| 色综合桃花网| 日韩免费一区二区三区| 蜜桃久久av一区| 国产97免费视频| 欧美电影免费提供在线观看| 国产高清视频色在线www| 久久国产精品久久| 蜜桃视频免费观看一区| 97成人资源站| 亚洲国产精品久久| 欧美大片免费高清观看| 亚洲精品一区二区三区四区五区| 国内精品在线播放| 久久久久免费看| 亚洲久久久久久久久久| 福利精品在线| 97av中文字幕| 久久色成人在线| 91精品中文字幕| 午夜精品一区二区三区在线视 | 北岛玲heyzo一区二区| 亚洲精品乱码视频| 国产精品一二三区| 欧美日韩综合在线观看| 亚洲最新av在线| 99亚洲乱人伦aⅴ精品| 欧美性久久久久| 国产精品久久久久久久久果冻传媒| www.黄色国产| 国产97在线|日韩| 欧美国产免费| 天天躁日日躁aaaxxⅹ| 欧美一二三四区在线| 中文字幕21页在线看| 黄色影视在线观看| 国产日韩三级在线| 亚洲欧美国产高清va在线播放| 国产福利精品av综合导导航| 中文字幕免费一区二区| 精品人妻无码一区二区三区换脸|