前端讀者 | 嗨,你知道this嗎
本文來自 @position_柚子,地址:https://juejin.im/post/5995c7a76fb9a0247a60c407
在平時的程式碼中,相信大家經常用到 this
,可是你真的明白此 this
真的是你認為的 this
嗎?今天柚子君總結了一下平時用到的 this
的場景,大家走過路過不要錯過啊~
首先咱們先來看一下《JavaScript 高階程式設計》上是怎麼說的。
this
物件是在執行時基於函式的執行環境繫結的:在全域性函式中,this
等於 windows
,而當函式被作為某個物件的方法呼叫時,this
等於那個物件。
還有一種情況,在《深入理解 ES6》一書中寫道:
如果箭頭函式被非箭頭函式包含,則 this
繫結的是最近一層非箭頭函式的 this
,且不能通過 call()、apply() 或 bind()
方法來改變 this 的值。
首先看一下非箭頭函式的情況:
一、普通函式呼叫
這是一個普通的函式宣告,在這種情況下,this
是指向 window
的:
var test = '哈哈哈';
function thisHandler() {
console.log('test:',this.test,'this:',this);
}
thisHandler() // test: 哈哈哈 this: window
其實上面的程式碼就相當於 window
thisHandler()
,所以這時 this
指向 window
var b = '哈哈哈';
function thisHandler() {
console.log('b:',this.b,'this:',this);
}
window.thisHandler() // b: 哈哈哈 this: window
二、作為物件的方法呼叫
當作為物件的方法被呼叫時,this
這時就指向呼叫它的物件。
var thisHandler = { name: "柚子", test: function(){ console.log('my name:',this.name); } } thisHandler.test() // my name: 柚子
再來一個栗子:
var thisHandler = {
name: "柚子",
fn: {
name: '芒果',
test: function() {
console.log('my name:',this.name);
}
}
}
thisHandler.fn.test() // my name: 芒果
這時 this
指向的是物件 fn
了,所以,關於物件呼叫這一點明白了嗎,如果明白了,那沒關係,接著看下一個強化題:
var name = '柚子'
var thisHandler = {
name: "芒果",
fn: {
name: '糖果',
test: function(){
console.log('my name:',this.name);
}
}
}
var testHandler = thisHandler.fn.test
testHandler()
這裡是一秒鐘分割線
噠噠噠,答對了,這裡的 this
指向的 window
,那麼這是為什麼呢,哪位小盆友來回答一下。舉手:
上面說到了,this
指向的是最後呼叫它的物件,第一步是賦值給了 testHandler
,最後執行的那一句相當於 window.testHandler()
。所以這裡的 this
指向的是 window
。最後輸出的就是 my name: 柚子
。
噠噠噠,真聰明,來闖下一關~
三、建構函式的呼叫
var name = '柚子'
function Bar() {
this.name = '芒果'
}
var handlerA = new Bar();
console.log(handlerA.name); // 芒果
console.log(name) // 柚子
其實要明白為什麼會是這樣一個結果,咱們就要來聊聊 new
做了哪些事情。
- 建立類的例項。這步是把一個空的物件的
__proto__
屬性設定為Bar.prototype
。 - 初始化例項。函式
Bar
被傳入引數並呼叫,關鍵字this
被設定為該例項。 - 返回例項。
弄明白了 new
的工作內容,自然而然的也明白了上面輸出的原因。
Bar()
中的 this
指向物件 handlerA
,並不是全域性物件。
四、apply / call 呼叫
使用 apply
方法可以改變 this
的指向。如果這個函式處於非嚴格模式下,則指定為 null
或 undefined
時會自動指向全域性物件(瀏覽器中就是window物件)。
var name = '芒果';
var thisHandler = {
name: "柚子",
test: function(){
console.log('my name:',this.name);
}
};
thisHandler.test(); // my name: 柚子
thisHandler.test.apply(); // my name: 芒果
四、箭頭函式
在《深入理解 ES6》一書中可以知道箭頭函式和普通函式的一個不同之處就在於 this 的繫結。
箭頭函式中沒有 this
繫結,必須通過查詢作用域鏈來決定其值。如果箭頭函式被非箭頭函式包含,則 this
繫結的是最近一層非箭頭函式的 this
;否則,this
的值會被設定為 undefined
。
var name = '柚子'
var thisHandler = {
name: '芒果',
test:() => {
console.log('my name:',this.name,'this:',this);
}
}
thisHandler.test(); // my name: 柚子 this: Window
這時 this
不是指向 thisHandler
,而是 Window
。
關於 this
的使用和體會還是要在平時運用中理解,先了解其原理,那麼在使用的時候就如魚得水啦。