自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

換個(gè)思路理解Javascript中的this

開(kāi)發(fā) 前端 開(kāi)發(fā)工具
在網(wǎng)上很多文章都對(duì) Javascript 中的 this 做了詳細(xì)的介紹,但大多是介紹各個(gè)綁定方式或調(diào)用方式下 this 的指向,于是我想有一個(gè)統(tǒng)一的思路來(lái)更好理解 this 指向,使大家更好判斷,以下有部分內(nèi)容不是原理,而是一種解題思路。

在網(wǎng)上很多文章都對(duì) Javascript 中的 this 做了詳細(xì)的介紹,但大多是介紹各個(gè)綁定方式或調(diào)用方式下 this 的指向,于是我想有一個(gè)統(tǒng)一的思路來(lái)更好理解 this 指向,使大家更好判斷,以下有部分內(nèi)容不是原理,而是一種解題思路。

從call方法開(kāi)始

call 方法允許切換函數(shù)執(zhí)行的上下文環(huán)境(context),即 this 綁定的對(duì)象。

大多數(shù)介紹 this 的文章中都會(huì)把 call 方法放到***介紹,但此文我們要把 call 方法放在***位介紹,并從 call 方法切入來(lái)研究 this ,因?yàn)?call 函數(shù)是顯式綁定 this 的指向,我們來(lái)看看它如何模擬實(shí)現(xiàn)(不考慮傳入 null 、 undefined 和原始值):

  1. Function.prototype.call = function(thisArg) { 
  2.     var context = thisArg; 
  3.     var arr = []; 
  4.     var result; 
  5.  
  6.     context.fn = this; 
  7.  
  8.     for (let i = 1, len = arguments.length; i < len; i++) { 
  9.         arr.push('arguments[' + i + ']'); 
  10.     } 
  11.  
  12.     result = eval("context.fn(" + arr + ")"); 
  13.  
  14.     delete context.fn; 
  15.  
  16.     return result; 
  17.  

從以上代碼我們可以看到,把調(diào)用 call 方法的函數(shù)作為***個(gè)參數(shù)對(duì)象的方法,此時(shí)相當(dāng)于把***個(gè)參數(shù)對(duì)象作為函數(shù)執(zhí)行的上下文環(huán)境,而 this 是指向函數(shù)執(zhí)行的上下文環(huán)境的,因此 this 就指向了***個(gè)參數(shù)對(duì)象,實(shí)現(xiàn)了 call 方法切換函數(shù)執(zhí)行上下文環(huán)境的功能。

對(duì)象方法中的this

在模擬 call 方法的時(shí)候,我們使用了對(duì)象方法來(lái)改變 this 的指向。調(diào)用對(duì)象中的方法時(shí),會(huì)把對(duì)象作為方法的上下文環(huán)境來(lái)調(diào)用。

既然 this 是指向執(zhí)行函數(shù)的上下文環(huán)境的,那我們先來(lái)研究一下調(diào)用函數(shù)時(shí)的執(zhí)行上下文情況。

下面我門(mén)來(lái)看看調(diào)用對(duì)象方法時(shí)執(zhí)行上下文是如何的:

  1. var foo = { 
  2.     x : 1, 
  3.     getX: function(){ 
  4.         console.log(this.x); 
  5.     } 
  6. foo.getX(); 

 

從上圖中,我們可以看出getX方法的調(diào)用者的上下文是foo,因此getX方法中的 this 指向調(diào)用者上下文foo,轉(zhuǎn)換成 call 方法為foo.getX.call(foo)。

下面我們把其他函數(shù)的調(diào)用方式都按調(diào)用對(duì)象方法的思路來(lái)轉(zhuǎn)換。

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

  1. function Foo(){ 
  2.     this.x = 1; 
  3.     this.getX = function(){ 
  4.         console.log(this.x); 
  5.     } 
  6. var foo = new Foo(); 
  7. foo.getX();  

執(zhí)行 new 如果不考慮原型鏈,只考慮上下文的切換,就相當(dāng)于先創(chuàng)建一個(gè)空的對(duì)象,然后把這個(gè)空的對(duì)象作為構(gòu)造函數(shù)的上下文,再去執(zhí)行構(gòu)造函數(shù),***返回這個(gè)對(duì)象。

  1. var newMethod = function(func){ 
  2.     var context = {}; 
  3.     func.call(context); 
  4.     return context; 
  5. function Foo(){ 
  6.     this.x = 1; 
  7.     this.getX = function(){ 
  8.         console.log(this.x); 
  9.     } 
  10. var foo = newMethod(Foo); 
  11. foo.getX(); 

 

DOM事件處理函數(shù)中的this

  1. DOMElement.addEventListener('click'function(){ 
  2.  
  3.   console.log(this); 
  4.  
  5. });  

把函數(shù)綁定到DOM事件時(shí),可以當(dāng)作在DOM上增加一個(gè)函數(shù)方法,當(dāng)觸發(fā)這個(gè)事件時(shí)調(diào)用DOM上對(duì)應(yīng)的事件方法。

  1. DOMElement.clickHandle = function(){ 
  2.     console.log(this); 
  3. DOMElement.clickHandle(); 

 

普通函數(shù)中的this

  1. var x = 1; 
  2. function getX(){ 
  3.     console.log(this.x); 
  4. getX();  

這種情況下,我們創(chuàng)建一個(gè)虛擬上下文對(duì)象,然后普通函數(shù)作為這個(gè)虛擬上下文對(duì)象的方法調(diào)用,此時(shí)普通函數(shù)中的this就指向了這個(gè)虛擬上下文。

那這個(gè)虛擬上下文是什么呢?在非嚴(yán)格模式下是全局上下文,瀏覽器里是 window ,NodeJs里是 Global ;在嚴(yán)格模式下是 undefined 。

  1. var x = 1; 
  2. function getX(){ 
  3.     console.log(this.x); 
  4.  
  5. [viturl context].getX = getX; 
  6. [viturl context].getX(); 

 

閉包中的this

  1. var x = 1; 
  2. var foo = { 
  3.     x: 2, 
  4.     y: 3, 
  5.     getXY: function(){ 
  6.         (function(){ 
  7.             console.log("x:" + this.x); 
  8.             console.log("y:" + this.y);  
  9.         })(); 
  10.     } 
  11. foo.getXY();  

這段代碼的上下文如下圖:

 

這里需要注意的是,我們?cè)傺芯亢瘮?shù)中的 this 指向時(shí),只需要關(guān)注 this 所在的函數(shù)是如何調(diào)用的, this 所在函數(shù)外的函數(shù)調(diào)用都是浮云,是不需要關(guān)注的。因此在所有的圖示中,我們只需要關(guān)注紅色框中的內(nèi)容。

因此這段代碼我們關(guān)注的部分只有:

  1. (function(){ 
  2.     console.log(this.x); 
  3. })();  

與普通函數(shù)調(diào)用一樣,創(chuàng)建一個(gè)虛擬上下文對(duì)象,然后普通函數(shù)作為這個(gè)虛擬上下文對(duì)象的方法立即調(diào)用,匿名函數(shù)中的 this 也就指向了這個(gè)虛擬上下文。

 

參數(shù)中的this

  1. var x = 1; 
  2. var foo = { 
  3.     x: 2, 
  4.     getX: function(){ 
  5.         console.log(this.x); 
  6.     } 
  7. setTimeout(foo.getX, 1000);  

函數(shù)參數(shù)是值傳遞的,因此上面代碼等同于以下代碼:

  1. var getX = function(){ 
  2.     console.log(this.x); 
  3. }; 
  4. setTimeout(getX, 1000);  

然后我們又回到了普通函數(shù)調(diào)用的問(wèn)題。

全局中的this

全局中的 this 指向全局的上下文

  1. var x = 1; 
  2. console.log(this.x); 

 

復(fù)雜情況下的this

  1. var x = 1; 
  2. var a = { 
  3.     x: 2, 
  4.     b: function(){ 
  5.         return function(){ 
  6.             return function foo(){ 
  7.                 console.log(this.x); 
  8.             }         
  9.         } 
  10.     } 
  11. }; 
  12.  
  13. (function(){ 
  14.     var x = 3; 
  15.     a.b()()(); 
  16. })();  

看到上面的情況是有很多個(gè)函數(shù),但我們只需要關(guān)注 this 所在函數(shù)的調(diào)用方式,首先我們來(lái)簡(jiǎn)化一下如下:

  1. var x = 1; 
  2. (function(){ 
  3.     var x = 3; 
  4.     var foo = function(){ 
  5.         console.log(this.x); 
  6.     } 
  7.     foo(); 
  8. });  

this 所在的函數(shù) foo 是個(gè)普通函數(shù),我們創(chuàng)建一個(gè)虛擬上下文對(duì)象,然后普通函數(shù)作為這個(gè)虛擬上下文對(duì)象的方法立即調(diào)用。因此這個(gè) this指向了這個(gè)虛擬上下文。在非嚴(yán)格模式下是全局上下文,瀏覽器里是 window ,NodeJs里是 Global ;在嚴(yán)格模式下是 undefined 。

總結(jié)

在需要判斷 this 的指向時(shí),我們可以安裝這種思路來(lái)理解:

  • 判斷 this 在全局中OR函數(shù)中,若在全局中則 this 指向全局,若在函數(shù)中則只關(guān)注這個(gè)函數(shù)并繼續(xù)判斷。
  • 判斷 this 所在函數(shù)是否作為對(duì)象方法調(diào)用,若是則 this 指向這個(gè)對(duì)象,否則繼續(xù)操作。
  • 創(chuàng)建一個(gè)虛擬上下文,并把this所在函數(shù)作為這個(gè)虛擬上下文的方法,此時(shí) this 指向這個(gè)虛擬上下文。
  • 在非嚴(yán)格模式下虛擬上下文是全局上下文,瀏覽器里是 window ,Node.js里是 Global ;在嚴(yán)格模式下是 undefined 。

圖示如下: 

責(zé)任編輯:龐桂玉 來(lái)源: segmentfault
相關(guān)推薦

2022-07-29 11:06:47

架構(gòu)開(kāi)發(fā)

2012-12-25 09:38:41

JavaScript設(shè)計(jì)模式

2020-08-23 11:32:21

JavaScript開(kāi)發(fā)技術(shù)

2024-07-18 10:12:04

2022-08-16 09:03:01

JavaScript前端

2020-12-16 09:47:01

JavaScript箭頭函數(shù)開(kāi)發(fā)

2011-03-22 09:49:15

JavaScript

2021-01-06 08:03:00

JavaScript數(shù)據(jù)結(jié)構(gòu)

2015-09-14 15:23:44

JavaScriptfunction

2015-09-02 11:22:36

JavaScript實(shí)現(xiàn)思路

2020-10-12 08:35:22

JavaScript

2013-11-05 13:29:04

JavaScriptreplace

2016-11-22 11:08:34

asyncjavascript

2017-11-20 16:17:50

智慧城市

2018-05-10 14:20:18

前端JavaScript深拷貝

2016-09-18 20:53:16

JavaScript閉包前端

2020-02-20 14:00:15

JavaScript原型原型鏈

2024-06-21 08:32:24

2023-02-08 08:47:13

計(jì)算機(jī)網(wǎng)絡(luò)MAC

2021-02-17 11:25:33

前端JavaScriptthis
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)