一、方法定義:
- apply:調用一個對象的一個方法,用另一個對象替換當前對象。例如:B.apply(A, arguments);即A對象應用B對象的方法。
- call:調用一個對象的一個方法,用另一個對象替換當前對象。例如:B.call(A, args1,args2);即A對象調用B對象的方法。
上面的定義看一遍是很懵的,不過自己遍寫例子遍反覆讀的時候,會有種撥開雲霧的感覺。
call 與 apply 的相同點:
- 方法的含義是一樣的,即方法功能是一樣的;
- 第一個參數的作用是一樣的;
call 與 apply 的不同點: 兩者傳入的列表形式不一樣
- call可以傳入多個參數;
- apply只能傳入兩個參數,所以其第二個參數往往是作爲數組形式傳入
存在的意義:實現(多重)繼承
二、舉個栗子
var name = '小張', age = 17;
var obj = {
name: '小劉',
objAge: this.age, //this指向window
myFun: function(){
return this.name + this.age; //this指向obj
}
}
console.log( obj.objAge ); //17
console.log( obj.myFun() ); //小劉 undefined
比較一下這兩者this的差別,第一個打印裏面的this指向obj,第二個全局聲明的shows()函數this是window。
- call()、 apply()、 bind() 都是用來重定義this這個對象的!
var name = '小張', age = 17;
var obj = {
name: '小劉',
objAge: this.age,
myFun: function(){
return this.name + this.age;
}
var db = {
name: '小黃',
age: 18
};
console.log( obj.myFun.call() ); //小張17 this指向window
console.log( obj.myFun.call(db) ); //小黃18 this指向對象db
console.log( obj.myFun.apply() ); //小張17
console.log( obj.myFun.apply(db) ); //小黃18
console.log( obj.myFun.bind()() ); //小張17 bind返回的是函數,必須調用才能執行
console.log( obj.myFun.bind(db)() ); //小黃18
- 對比call、 bind、 apply 傳參情況下
var name = '小張', age = 17
var obj = {
name: '小劉',
objAge: this.age,
myFun: function( fm, t ){
return this.name + this.age + '來自' + fm + '去往' + t;
}
}
var db = {
name: '小黃',
age: 18
};
console.log( obj.myFun.call(db, '江西', '深圳') ); //小黃18來自江西去往深圳
console.log( obj.myFun.apply(db, ['江西', '深圳']) ); //小黃18來自江西去往深圳
console.log( obj.myFun.bind(db, '江西', '深圳')() ); //小黃18來自江西去往深圳
從上面的結果來看:
call、 bind、 apply 這三個函數的第一個參數都是this的指向對象,
第二個參數差別就來了:
call 的參數是直接放進去的,第二第三第n個參數全都用逗號分隔,直接放到後面obj.myFun.call(db,‘江西’, …, ‘string’)。
apply的所有參數都必須放在一個數組裏面傳進去。
bind除了返回函數以外,它的參數和call 一樣。
當然,三者的參數不限定是String 類型,允許是各種類型,包括函數,對象等等。