最近在讀《javascript高級程序設計》疏通經脈,經過寫文的方式增強本身理解。javascript
在前端面試的問題中少不了this
指向的問題,而如下三種方法均可以改變this
指向:前端
apply()
和call()
兩個方法的用途都是在特定的做用域中調用函數,實際上等於設置函數體內的this
對象的值。apply()
方法接受兩個參數:java
thisArg
thisArg
該參數可選填,在func 函數
運行時使用的this
值。若是這個函數處於非嚴格模式下,則指定爲null
或undefined
時會自動替換爲指向全局對象,原始值會被包裝。若是該參數缺失時則指向全局對象。面試
argsArray
argsArray
該參數可選填,接受一個數組或arguments(arguments知識傳送門:javascript:函數屬性梳理)。若是不填寫則表明不須要傳參。數組
let o1 = {
number: 100
}
let o2 = {
number: 200
}
function sum (num1, num2) {
console.log(num1 + num2 + this.number)
}
sum.apply(o1, [1, 10]) // 111 將this指向o1
sum.apply(o2, [1, 10]) // 211 將this指向o2
複製代碼
apply()
不只能傳參,最重要的是能夠改變函數賴以運行的做用域!!!在上面的例子中,當傳入o1
時,this.number
指向了o1
裏的number
;當傳入o2
時,this.number
指向了o2
裏的number
。瀏覽器
理解了
apply()
,那理解call()
便不費吹灰之力。由於call()
與apply()
方法惟一的區別在於第二個參 接受參數的形式不一樣,做用徹底相同。call()傳遞給函數的參數只能逐個列舉出來,看下面的例子:bash
function sum (num1, num2) {
console.log(num1 + num2)
}
sum.call(o1, 1, 10) // 11
複製代碼
bind()
方法建立一個新的函數,在調用時設置this
關鍵字爲提供的值。並在調用新函數時,將給定參數列表做爲原函數的參數序列的前若干項。和call()
與apply()
的區別在於:bind()
會建立一個原函數的拷貝
(綁定函數),擁有指定的this
值和初始參數,並返回這個函數。看下MDN裏的描述:app
bind()
最簡單的用法是建立一個函數,不論怎麼調用,這個函數都有一樣的this
值。JavaScript
新手常常犯的一個錯誤是將一個方法從對象中拿出來,而後再調用,指望方法中的this
是原來的對象(好比在回調中傳入這個方法)。若是不作特殊處理的話,通常會丟失原來的對象。基於這個函數,用原始的對象建立一個綁定函數,巧妙地解決了這個問題:函數
this.x = 9; // 在瀏覽器中,this指向全局的 "window" 對象
var module = {
x: 81,
getX: function() { return this.x; }
};
module.getX(); // 81
var retrieveX = module.getX;
retrieveX();
// 返回9 - 由於函數是在全局做用域中調用的
// 建立一個新函數,把 'this' 綁定到 module 對象
// 新手可能會將全局變量 x 與 module 的屬性 x 混淆
var boundGetX = retrieveX.bind(module);
boundGetX(); // 81
複製代碼
關於call、apply和bind函數的做用極其類似,但有不一樣之處,關於如何更好運用還得在探索。post
參考資料:
種一棵樹最好的時間是十年前。