JS中的this


本文從兩方面討論this常規函數箭頭函數

 

首先明確:this指向JavaScript實例,因此只有在函數調用時才可以確定下來,而在函數聲明時是無法確定的!

 

一、全局中的this

無論是否在嚴格模式下,在全局執行環境中(在任何函數體外部)this 都指向全局對象。

// 在瀏覽器中, window 對象同時也是全局對象:console.log(this === window); // true

二、常規函數中的this

1.純粹的函數調用

 1 //----------------------------example1-------------------------------
 2 // 非嚴格模式下
 3 function f1(){
 4     return this;
 5 }
 6 //在瀏覽器中:
 7 f1() === window;   //在瀏覽器中,全局對象是window
 8 
 9 //在Node中:
10 f1() === global; // true
11 
12 //----------------------------example2-------------------------------
13 // 嚴格模式下
14 function f2(){
15     "use strict"; // 這里是嚴格模式
16     return this;
17 }
18 
19 f2() === undefined; // true 此處的this為undefined是因為f2是直接被調用的,而不是作為某個對象的方法(如 window.f2())被調用。
20 
21 //----------------------------example3-------------------------------
22 // 將一個對象作為call和apply的第一個參數,this會被綁定到這個對象。
23 var obj = {a: 'Custom'};
24 
25 // 這個屬性是在global對象定義的。
26 var a = 'Global';
27 
28 function whatsThis(arg) {
29     return this.a;  // this的值取決於函數的調用方式
30 }
31 
32 whatsThis();          // 寫法1,嚴格模式為undefined,非嚴格模式為'Global'
33 whatsThis.call(undefined); // 寫法2,嚴格模式為undefined,非嚴格模式為'Global'
34 whatsThis.call(obj);  // 可指定this,'Custom'
35 whatsThis.apply(obj); // 可指定this,'Custom'
36 whatsThis.bind(obj)(); // 可綁定this,'Custom'
37 whatsThis.bind(obj).bind({a: 'aHhha'})(); // this只可綁定一次,'Custom'

 

上面的寫法1寫法2是等價的,寫法1寫法2 的語法糖。

寫法2中call方法接收的第一個參數就是this,這里傳了一個undefined,此時有如下定義:

如果你傳的 context 是 null 或者 undefined,那么非嚴格模式下, window 對象(瀏覽器)或global(Node)就是默認的 context,嚴格模式下默認 context是 undefined。

 

2.對象中的函數的this

當函數作為對象里的方法被調用時,它們的 this 是調用該函數的對象。最靠近的引用優先級最高。

 1 var o = {prop: 37};
 2 
 3 function independent() {
 4   return this.prop;
 5 }
 6 
 7 o.f = independent;
 8 
 9 console.log(o.f()); // logs 37, 函數調用關系為從o的f成員調用
10 
11 o.b = {g: independent, prop: 42};
12 console.log(o.b.g()); // 42 最靠近的引用優先級最高
13 console.log(o.f.call({prop: 53}));  // 使用call可改變this

 

3.構造函數中的this

當函數作為構造函數被new返回一個對象時,該對象即為this。

 1 function C(){
 2   this.a = 37;
 3 }
 4 
 5 var o = new C();
 6 console.log(o.a); // logs 37
 7 
 8 
 9 function C2(){
10   this.a = 37;
11   return {a:38};
12 }
13 
14 o = new C2();
15 console.log(o.a); // logs 38

 

4.作為DOM元素的監聽處理函數的this

當函數被作為DOM元素的監聽處理函數時,它的this指向監聽器所在的DOM元素,但只有最外層代碼中的this是這樣的:

1 <button onclick="alert(this.tagName.toLowerCase());">  <!-- button -->
2   Show this
3 </button>
4 <button onclick="alert((function(){return this})());">  <!-- 非嚴格模式下指向global/window -->
5   Show inner this
6 </button>

 

5.window.setTimeout()和window.setInterval()的this

window.setTimeout()和window.setInterval()的函數中的this默認是window對象。

 

總結:常規函數中,有以下總結:

this只有在函數被調用時才能確定下來,this指向調用函數的對象;this最靠近的引用優先級最高;可以用call()或bind()指定this;構造函數的this指向new返回的對象;DOM元素的監聽處理函數的this指向監聽器所在的DOM元素;window.setTimeout()和window.setInterval()的函數中的this默認是window對象。

 

三、箭頭函數的this

1.箭頭函數不會創建自己的this,它只會從自己的作用域鏈的上一層繼承this。

 1 function Person() {
 2   // Person() 構造函數定義 `this`作為它自己的實例.
 3   this.age = 0;
 4 
 5   setInterval(function growUp() {
 6     // 在非嚴格模式, growUp()函數定義 `this`作為全局對象, 
 7     // 與在 Person()構造函數中定義的 `this`並不相同.
 8     this.age++;
 9     console.log(this.age) //NAN
10   }, 1000);
11 }
12 
13 var p = new Person();

 

1 function Person(){
2   this.age = 0;
3 
4   setInterval(() => {
5     this.age++; // |this| 正確地指向 p 實例,繼承作用域鏈 箭頭函數=>Person
6   }, 1000);
7 }
8 
9 var p = new Person();

 

2.箭頭函數不能用call()指定this

1 const obj = {
2     a: () => {
3         console.log(this)
4     }
5 }
6 obj.a.call('123')  //window,繼承作用域鏈 箭頭函數=>window

  

3.箭頭函數不能用bind()指定this

1 var globalObject = this;
2 var foo = (() => this);
3 var obj = {foo: foo};
4 foo = foo.bind(obj);
5 console.log(foo() === globalObject); // true

 

總結:箭頭函數中,有以下總結:

箭頭函數不會創建自己的this,它只會從自己的作用域鏈的上一層繼承this;箭頭函數不能用call()或bind()指定this

 

歡迎留言交流。 

本文參考:

https://juejin.im/post/5aa1eb056fb9a028b77a66fd

https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/this

https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Functions/arrow_functions

 

2019.9.12

yangqianqian

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM