一直以來,你們都對函數的調用有不少的疑惑,特別是this指針的指向。 其實理解了核心的原理以後,就很容易理解,甚至就是套用數學公式同樣!javascript
讓咱們看看原始的函數調用語句,也就是call方法java
function test(param){
console.log(this + " loves " + param);
}
複製代碼
test.call("Warren", "you") //=> Warren loves you數組
能夠看到,咱們調用了test方法,而且把this指向Warren,傳入參數you。這就是javascript函數調用的核心概念。其餘函數均可以參考這個概念。bash
若果每次調用函數都用call,會變得很麻煩。Javascript容許咱們直接調用test("you"),其實就至關於閉包
function test(param) {
console.log("loves " + thing);
}
// this:
test("you")
// 至關於:
test.call(window, "you");
複製代碼
可是這個在ECMAScript的strict模式會變成:app
// this:
test("you")
// 至關於:
test.call(undefined, "you");
複製代碼
歸納就是兩條公式:函數
fn(...args) 就至關於 fn.call(window [ES5-strict: undefined], ...args).ui
(function() {})() 就至關於 (function() {}).call(window [ES5-strict: undefined).this
另外一種常見的函數調用方法就是obj.test()
.es5
var obj = {
name: "Warren",
test: function(params) {
console.log(this + " loves " + params);
}
}
// this:
obj.test("you")
// 至關於:
obj.test.call(obj, "you");
複製代碼
能夠看到this指向了obj,咱們以前是單獨聲明test,再看看若是將它咱們關聯給其餘對象。
test: function(params) {
console.log(this + " loves " + params);
}
var obj = {
name: "Warren",
}
obj.test = test;
obj.test("you")
// 仍然至關於 obj.test.call(test, "you")
test("you") // "[object DOMWindow]you"
複製代碼
this指針根據調用者的變化而變化!
Function.prototype.bind
有時候須要根據調用者來改變this指向,這能夠用簡單閉包來實現
var obj = {
name: "Warren",
test: function(params) {
console.log(this + " loves " + params);
}
}
var boundTest = function(params) { return obj.test.call(obj, params); }
boundTest("you");
複製代碼
套用以前的公式 fn(...args) 就至關於 fn.call(window [ES5-strict: undefined], ...args).
boundTest("you"); => boundTest(window,"you"),可是咱們在boundTest裏面已經將test的this指向了obj!
讓咱們改造一下這個函數:
var bind = function(func, thisValue) {
return function() {
return func.apply(thisValue, arguments);
}
}
var boundTest = bind(obj.test, obj);
boundTest(you) // "Warren loves you"
複製代碼
要理解上面的代碼,只須要知道2點。
上面只是爲了更好理解,其實es5原本就有一個bind函數
var boundTest = obj.test.bind(obj);
boundTest(you) // "Warren loves you"
複製代碼
以上大概就是JavaScript函數調用與this 指針的基本原理,只要記住這兩條公式,基本就不虛了。
fn(...args) 就至關於 fn.call(window [ES5-strict: undefined], ...args).
(function() {})() 就至關於 (function() {}).call(window [ES5-strict: undefined).