本文從兩方面討論this:常規函數和箭頭函數html
首先明確:this指向JavaScript實例,所以只有在函數調用時才能夠肯定下來,而在函數聲明時是沒法肯定的!瀏覽器
1、全局中的thisapp
不管是否在嚴格模式下,在全局執行環境中(在任何函數體外部)this 都指向全局對象。函數
// 在瀏覽器中, window 對象同時也是全局對象:console.log(this === window); // truepost
2、常規函數中的thisthis
1.純粹的函數調用spa
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 的語法糖。code
寫法2中call方法接收的第一個參數就是this,這裏傳了一個undefined,此時有以下定義:htm
若是你傳的 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對象。
3、箭頭函數的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。
歡迎留言交流。
本文參考:
http://www.javashuo.com/article/p-aaovngvq-gs.html
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
原文出處:https://www.cnblogs.com/halao/p/11512791.html