日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

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

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
換個思路理解Javascript中的this

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

成都創(chuàng)新互聯(lián)公司是創(chuàng)新、創(chuàng)意、研發(fā)型一體的綜合型網(wǎng)站建設(shè)公司,自成立以來公司不斷探索創(chuàng)新,始終堅持為客戶提供滿意周到的服務(wù),在本地打下了良好的口碑,在過去的10年時間我們累計服務(wù)了上千家以及全國政企客戶,如隧道混凝土攪拌車等企業(yè)單位,完善的項目管理流程,嚴格把控項目進度與質(zhì)量監(jiān)控加上過硬的技術(shù)實力獲得客戶的一致贊美。

從call方法開始

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

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

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

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

對象方法中的this

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

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

下面我門來看看調(diào)用對象方法時執(zhí)行上下文是如何的:

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

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

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

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

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

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

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

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

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

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

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

普通函數(shù)中的this

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

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

那這個虛擬上下文是什么呢?在非嚴格模式下是全局上下文,瀏覽器里是 window ,NodeJs里是 Global ;在嚴格模式下是 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. }
  12. foo.getXY(); 

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

這里需要注意的是,我們再研究函數(shù)中的 this 指向時,只需要關(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)建一個虛擬上下文對象,然后普通函數(shù)作為這個虛擬上下文對象的方法立即調(diào)用,匿名函數(shù)中的 this 也就指向了這個虛擬上下文。

參數(shù)中的this

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

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

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

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

全局中的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. (function(){
  13.     var x = 3;
  14.     a.b()()();
  15. })(); 

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

 
 
 
 
  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 是個普通函數(shù),我們創(chuàng)建一個虛擬上下文對象,然后普通函數(shù)作為這個虛擬上下文對象的方法立即調(diào)用。因此這個 this指向了這個虛擬上下文。在非嚴格模式下是全局上下文,瀏覽器里是 window ,NodeJs里是 Global ;在嚴格模式下是 undefined 。

總結(jié)

在需要判斷 this 的指向時,我們可以安裝這種思路來理解:

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

圖示如下:


當前名稱:換個思路理解Javascript中的this
地址分享:http://www.dlmjj.cn/article/dhjigpg.html