成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

換個思路理解Javascript中的this

開發 前端 開發工具
在網上很多文章都對 Javascript 中的 this 做了詳細的介紹,但大多是介紹各個綁定方式或調用方式下 this 的指向,于是我想有一個統一的思路來更好理解 this 指向,使大家更好判斷,以下有部分內容不是原理,而是一種解題思路。

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

從call方法開始

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

大多數介紹 this 的文章中都會把 call 方法放到***介紹,但此文我們要把 call 方法放在***位介紹,并從 call 方法切入來研究 this ,因為 call 函數是顯式綁定 this 的指向,我們來看看它如何模擬實現(不考慮傳入 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.  

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

對象方法中的this

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

既然 this 是指向執行函數的上下文環境的,那我們先來研究一下調用函數時的執行上下文情況。

下面我門來看看調用對象方法時執行上下文是如何的:

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

 

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

下面我們把其他函數的調用方式都按調用對象方法的思路來轉換。

構造函數中的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();  

執行 new 如果不考慮原型鏈,只考慮上下文的切換,就相當于先創建一個空的對象,然后把這個空的對象作為構造函數的上下文,再去執行構造函數,***返回這個對象。

  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事件處理函數中的this

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

把函數綁定到DOM事件時,可以當作在DOM上增加一個函數方法,當觸發這個事件時調用DOM上對應的事件方法。

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

 

普通函數中的this

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

這種情況下,我們創建一個虛擬上下文對象,然后普通函數作為這個虛擬上下文對象的方法調用,此時普通函數中的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. foo.getXY();  

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

 

這里需要注意的是,我們再研究函數中的 this 指向時,只需要關注 this 所在的函數是如何調用的, this 所在函數外的函數調用都是浮云,是不需要關注的。因此在所有的圖示中,我們只需要關注紅色框中的內容。

因此這段代碼我們關注的部分只有:

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

與普通函數調用一樣,創建一個虛擬上下文對象,然后普通函數作為這個虛擬上下文對象的方法立即調用,匿名函數中的 this 也就指向了這個虛擬上下文。

 

參數中的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);  

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

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

然后我們又回到了普通函數調用的問題。

全局中的this

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

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

 

復雜情況下的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. })();  

看到上面的情況是有很多個函數,但我們只需要關注 this 所在函數的調用方式,首先我們來簡化一下如下:

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

this 所在的函數 foo 是個普通函數,我們創建一個虛擬上下文對象,然后普通函數作為這個虛擬上下文對象的方法立即調用。因此這個 this指向了這個虛擬上下文。在非嚴格模式下是全局上下文,瀏覽器里是 window ,NodeJs里是 Global ;在嚴格模式下是 undefined 。

總結

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

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

圖示如下: 

責任編輯:龐桂玉 來源: segmentfault
相關推薦

2022-07-29 11:06:47

架構開發

2012-12-25 09:38:41

JavaScript設計模式

2020-08-23 11:32:21

JavaScript開發技術

2024-07-18 10:12:04

2022-08-16 09:03:01

JavaScript前端

2020-12-16 09:47:01

JavaScript箭頭函數開發

2021-01-06 08:03:00

JavaScript數據結構

2011-03-22 09:49:15

JavaScript

2015-09-14 15:23:44

JavaScriptfunction

2015-09-02 11:22:36

JavaScript實現思路

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

智慧城市

2024-06-21 08:32:24

2020-02-20 14:00:15

JavaScript原型原型鏈

2016-09-18 20:53:16

JavaScript閉包前端

2018-05-10 14:20:18

前端JavaScript深拷貝

2023-02-08 08:47:13

計算機網絡MAC

2021-02-17 11:25:33

前端JavaScriptthis
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 精品欧美一区二区三区免费观看 | 国产欧美视频一区二区三区 | 国产一二三区在线 | 久久精品国产一区二区电影 | 国产日产精品一区二区三区四区 | 中文字幕一区二区三区不卡在线 | 亚洲国产aⅴ成人精品无吗 国产精品永久在线观看 | aaaaaa大片免费看最大的 | 91精品在线观看入口 | 色网站在线| 精品视频免费 | 亚洲视频在线观看 | 色综合桃花网 | 在线观看免费黄色片 | 可以看黄的视频 | 在线看无码的免费网站 | www.久久.com| 国产高清一区二区 | 91精品国产91久久久久游泳池 | 99精品亚洲国产精品久久不卡 | 中文字幕国产 | 国产在线精品一区二区三区 | 免费高潮视频95在线观看网站 | 日韩一区二区三区四区五区 | 日韩在线精品视频 | 三级黄视频在线观看 | 中文字幕视频三区 | 国产一区二区三区视频 | 成人国产精品久久久 | 久久久久久久久一区 | 久久国产欧美日韩精品 | 成人区一区二区三区 | 亚洲成人一区二区 | 国产精品伦理一区二区三区 | 亚洲伊人久久综合 | 亚洲一区二区精品视频在线观看 | 免费看国产a | 亚洲一区 中文字幕 | 草久久免费视频 | 精品影院 | 亚洲一区二区久久 |