日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問(wèn)題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷解決方案
JavaScript中this的運(yùn)行機(jī)制及爬坑指南

在 JavaScript 中,this 這個(gè)特殊的變量是相對(duì)比較復(fù)雜的,因?yàn)?this 不僅僅用在面向?qū)ο蟓h(huán)境中,在其他任何地方也是可用的。 本篇博文中會(huì)解釋 this 是如何工作的以及使用中可能導(dǎo)致問(wèn)題的地方,***奉上***實(shí)踐。

創(chuàng)新互聯(lián)公司是一家專業(yè)提供新和企業(yè)網(wǎng)站建設(shè),專注與網(wǎng)站設(shè)計(jì)、做網(wǎng)站H5高端網(wǎng)站建設(shè)、小程序制作等業(yè)務(wù)。10年已為新和眾多企業(yè)、政府機(jī)構(gòu)等服務(wù)。創(chuàng)新互聯(lián)專業(yè)網(wǎng)站建設(shè)公司優(yōu)惠進(jìn)行中。

為了更好地理解 this,將 this 使用的場(chǎng)景分成三類:

  • 在函數(shù)內(nèi)部 this 一個(gè)額外的,通常是隱含的參數(shù)。
  • 在函數(shù)外部(***作用域中): 這指的是瀏覽器中的全局對(duì)象或者 Node.js 中一個(gè)模塊的輸出。
  • 在傳遞給eval()的字符串中: eval() 或者獲取 this 當(dāng)前值值,或者將其設(shè)置為全局對(duì)象,取決于 this 是直接調(diào)用還是間接調(diào)用。

我們來(lái)看看每個(gè)類別。

this 在函數(shù)中

這是最常用的 this 使用方式,函數(shù)通過(guò)扮演三種不同的角色來(lái)表示 JavaScript 中的所有可調(diào)用結(jié)構(gòu)體:

  • 普通函數(shù)(this 在非嚴(yán)格模式下為全局對(duì)象,在嚴(yán)格模式下為undefined)
  • 構(gòu)造函數(shù)(this 指向新創(chuàng)建的實(shí)例)
  • 方法(this 是指方法調(diào)用的接收者)

在函數(shù)中,this 通常被認(rèn)為是一個(gè)額外的,隱含的參數(shù)。

this 在普通函數(shù)中

在普通函數(shù)中,this 的值取決于模式:

非嚴(yán)格模式: this 是指向全局對(duì)象 (在瀏覽器中為window對(duì)象)。

 
 
 
  1. function sloppyFunc() { 
  2.     console.log(this === window); // true 
  3. sloppyFunc();

嚴(yán)格模式: this 的值為 undefined。

 
 
 
  1. function strictFunc() { 
  2.     'use strict'; 
  3.     console.log(this === undefined); // true 
  4. strictFunc();

也就是說(shuō),this 是一個(gè)設(shè)定了默認(rèn)值(window或undefined)的隱式參數(shù)。 但是,可以通過(guò) call() 或 apply() 進(jìn)行函數(shù)調(diào)用,并明確指定this的值:

 
 
 
  1. function func(arg1, arg2) { 
  2.     console.log(this); // a 
  3.     console.log(arg1); // b 
  4.     console.log(arg2); // c 
  5. func.call('a', 'b', 'c'); // (this, arg1, arg2) 
  6. func.apply('a', ['b', 'c']); // (this, arrayWithArgs)

this 在構(gòu)造函數(shù)中

如果通過(guò)new運(yùn)算符調(diào)用函數(shù),則函數(shù)將成為構(gòu)造函數(shù)。 該運(yùn)算符創(chuàng)建一個(gè)新的對(duì)象,并通過(guò)this傳遞給構(gòu)造函數(shù):

 
 
 
  1. var savedThis; 
  2. function Constr() {
  3.     savedThis = this; 
  4. var inst = new Constr(); 
  5. console.log(savedThis === inst); // true 
  6. 在JavaScript中實(shí)現(xiàn),new運(yùn)算符大致如下所示(更精確的實(shí)現(xiàn)稍微復(fù)雜一點(diǎn)): 
  7. function newOperator(Constr, arrayWithArgs) { 
  8.     var thisValue = Object.create(Constr.prototype); 
  9.     Constr.apply(thisValue, arrayWithArgs); 
  10.     return thisValue; 
  11. }

this 在方法中

在方法中,類似于傳統(tǒng)的面向?qū)ο蟮恼Z(yǔ)言:this指向接受者,方法被調(diào)用的對(duì)象。

 
 
 
  1. var obj = { 
  2.     method: function () { 
  3.         console.log(this === obj); // true 
  4.     } 
  5. obj.method();

this 在***作用域中

在瀏覽器中,頂層作用域是全局作用域,它指向 global object(如window):

 
 
 
  1. console.log(this === window); // true

在Node.js中,通常在模塊中執(zhí)行代碼。 因此,***作用域是一個(gè)特殊的模塊作用域:

 
 
 
  1. // `global` (不是 `window`) 指全局對(duì)象: 
  2. console.log(Math === global.Math); // true 
  3. // `this` 不指向全局對(duì)象: 
  4. console.log(this !== global); // true 
  5. // `this` refers to a module’s exports: 
  6. console.log(this === module.exports); // true

this 在 eval() 中

eval() 可以被直接(通過(guò)真正的函數(shù)調(diào)用)或間接(通過(guò)其他方式)調(diào)用。

如果間接調(diào)用evaleval() ,則this指向全局對(duì)象:

 
 
 
  1. (0,eval)('this === window') 
  2. true

否則,如果直接調(diào)用eval() ,則this與eval()的環(huán)境中保持一致。 例如:

 
 
 
  1. // 普通函數(shù) 
  2. function sloppyFunc() { 
  3.     console.log(eval('this') === window); // true 
  4. sloppyFunc(); 
  5. function strictFunc() { 
  6.     'use strict'; 
  7.     console.log(eval('this') === undefined); // true 
  8. }
  9. strictFunc(); 
  10. // 構(gòu)造器 
  11. var savedThis; 
  12. function Constr() { 
  13.     savedThis = eval('this'); 
  14. var inst = new Constr(); 
  15. console.log(savedThis === inst); // true  
  16. // 方法 
  17. var obj = { 
  18.     method: function () { 
  19.         console.log(eval('this') === obj); // true 
  20.     } 
  21. obj.method();

與this相關(guān)的陷阱

有三個(gè)你需要知道的與this相關(guān)的陷阱。請(qǐng)注意,在各種情況下,嚴(yán)格模式更安全,因?yàn)閠his在普通函數(shù)中為undefined,并且會(huì)在出現(xiàn)問(wèn)題時(shí)警告。

陷阱:忘記new操作符

如果你調(diào)用一個(gè)構(gòu)造函數(shù)時(shí)忘記了new操作符,那么你意外地將this用在一個(gè)普通的函數(shù)。this會(huì)沒(méi)有正確的值。 在非嚴(yán)格模式下,this指向window對(duì)象,你將創(chuàng)建全局變量:

 
 
 
  1. function Point(x, y) { 
  2.     this.x = x; 
  3.     this.y = y; 
  4. var p = Point(7, 5); // 忘記new! 
  5. console.log(p === undefined); // true  
  6. // 創(chuàng)建了全局變量: 
  7. console.log(x); // 7 
  8. console.log(y); // 5 
  9. 幸運(yùn)的是,在嚴(yán)格模式下會(huì)得到警告(this === undefined): 
  10. function Point(x, y) { 
  11.     'use strict'; 
  12.     this.x = x; 
  13.     this.y = y; 
  14. var p = Point(7, 5); 
  15. // TypeError: Cannot set property 'x' of undefined

陷阱:不正確地提取方法

如果獲取方法的值(不是調(diào)用它),則可以將該方法轉(zhuǎn)換為函數(shù)。 調(diào)用該值將導(dǎo)致函數(shù)調(diào)用,而不是方法調(diào)用。 當(dāng)將方法作為函數(shù)或方法調(diào)用的參數(shù)傳遞時(shí),可能會(huì)發(fā)生這種提取。 實(shí)際例子包括setTimeout()和事件注冊(cè)處理程序。 我將使用函數(shù)callItt() 來(lái)模擬此用例:

 
 
 
  1. /**類似setTimeout() 和 setImmediate() */ 
  2. function callIt(func) { 
  3.     func(); 
  4. }

如果在非嚴(yán)格模式下把一個(gè)方法作為函數(shù)來(lái)調(diào)用,那么this將指向全局對(duì)象并創(chuàng)建全局變量:

 
 
 
  1. var counter = {
  2.     count: 0,
  3.     // Sloppy-mode method
  4.     inc: function () {
  5.         this.count++;
  6.     }
  7. }
  8. callIt(counter.inc);
  9. // Didn’t work:
  10. console.log(counter.count); // 0
  11. // Instead, a global variable has been created
  12. // (NaN is result of applying ++ to undefined):
  13. console.log(count); // NaN

如果在嚴(yán)格模式下把一個(gè)方法作為函數(shù)來(lái)調(diào)用,this為undefined。 同時(shí)會(huì)得到一個(gè)警告:

 
 
 
  1. var counter = { 
  2.     count: 0, 
  3.     // Strict-mode method 
  4.     inc: function () { 
  5.         'use strict'; 
  6.         this.count++; 
  7.     } 
  8. callIt(counter.inc); 
  9. // TypeError: Cannot read property 'count' of undefined 
  10. console.log(counter.count); 
  11. 修正方法是使用bind(): 
  12. var counter = { 
  13.     count: 0, 
  14.     inc: function () { 
  15.         this.count++; 
  16.     } 
  17. callIt(counter.inc.bind(counter)); 
  18. // 成功了! 
  19. console.log(counter.count); // 1

bind()創(chuàng)建了一個(gè)新的函數(shù),它總是能得到一個(gè)指向counter的this。

陷阱:shadowing this

當(dāng)在一個(gè)方法中使用普通函數(shù)時(shí),很容易忘記前者具有其自己this(即使其不需要this)。 因此,你不能從前者引用該方法的this,因?yàn)樵搕his會(huì)被遮蔽。 讓我們看看出現(xiàn)問(wèn)題的例子:

 
 
 
  1. var obj = { 
  2.     name: 'Jane', 
  3.     friends: [ 'Tarzan', 'Cheeta' ], 
  4.     loop: function () { 
  5.         'use strict'; 
  6.         this.friends.forEach( 
  7.             function (friend) { 
  8.                 console.log(this.name+' knows '+friend); 
  9.             } 
  10.         ); 
  11.     } 
  12. }; 
  13. obj.loop(); 
  14. // TypeError: Cannot read property 'name' of undefined

在前面的例子中,獲取this.name失敗,因?yàn)楹瘮?shù)的this個(gè)是undefined,它與方法loop()的不同。 有三種方法可以修正this。

修正1: that = this。 將它分配給一個(gè)沒(méi)有被遮蔽的變量(另一個(gè)流行名稱是self)并使用該變量。

 
 
 
  1. loop: function () { 
  2.     'use strict'; 
  3.     var that = this; 
  4.     this.friends.forEach(function (friend) { 
  5.         console.log(that.name+' knows '+friend); 
  6.     }); 
  7. }

修正2: bind()。 使用bind()來(lái)創(chuàng)建一個(gè)this總是指向正確值的函數(shù)(在下面的例子中該方法的this)。

 
 
 
  1. loop: function () { 
  2.     'use strict'; 
  3.     this.friends.forEach(function (friend) { 
  4.         console.log(this.name+' knows '+friend); 
  5.     }.bind(this)); 
  6. }

修正3: forEach的第二個(gè)參數(shù)。 此方法具有第二個(gè)參數(shù),this值將作為此值傳遞給回調(diào)函數(shù)。

 
 
 
  1. loop: function () { 
  2.     'use strict'; 
  3.     this.friends.forEach(function (friend) { 
  4.         console.log(this.name+' knows '+friend); 
  5.     }, this); 
  6. }

***實(shí)踐

從概念上講,我認(rèn)為普通函數(shù)沒(méi)有它自己的this,并且想到上述修復(fù)是為了保持這種想法。 ECMAScript 6通過(guò)箭頭函數(shù)支持這種方法 - 沒(méi)有它們自己的this。 在這樣的函數(shù)里面,你可以自由使用this,因?yàn)椴粫?huì)被屏蔽:

 
 
 
  1. loop: function () { 
  2.     'use strict'; 
  3.     // The parameter of forEach() is an arrow function 
  4.     this.friends.forEach(friend => { 
  5.         // `this` is loop’s `this` 
  6.         console.log(this.name+' knows '+friend); 
  7.     }); 
  8. }

我不喜歡使用this作為普通函數(shù)的附加參數(shù)的API:

 
 
 
  1. beforeEach(function () { 
  2.     this.addMatchers({ 
  3.         toBeInRange: function (start, end) { 
  4.             ... 
  5.         } 
  6.     }); 
  7. });

將這樣的隱含參數(shù)變成明確的參數(shù)使得事情更加明顯,并且與箭頭函數(shù)兼容。

 
 
 
  1. beforeEach(api => { 
  2.     api.addMatchers({ 
  3.         toBeInRange(start, end) { 
  4.             ... 
  5.         } 
  6.     }); 
  7. }); 

文章標(biāo)題:JavaScript中this的運(yùn)行機(jī)制及爬坑指南
URL分享:http://m.5511xx.com/article/codeoie.html