1. 程式人生 > >apply,call,bind的區別

apply,call,bind的區別

jscript ima 區別 tro say 動態 例子 lin proto

apply和call

在js中,apply,call,bind都是為了改變函數的執行上下文的而存在的,即改變函數內部this的指向。

下面的例子可以說明我們為什麽要用apply和call,以及apply和call的區別。

function Person(){};
Person.prototype = {
  name:‘John‘,
  sayName:function(type){
    console.log(this.name + " "+ type);
  }
}
var testPerson = new Person();

var lily = {name: ‘lily‘};

testPerson.sayName(‘prototype‘); // John prototype

testPerson.sayName.call(lily,‘call‘); //lily call

testPerson.sayName.apply(lily,[‘apply‘]); // lily apply

上面的代碼輸出結果如下圖所示:

技術分享

(1)可以看出 call 和 apply是為了動態改變this而出現的,testPerson.sayName(‘prototype‘) 中沒有指定一個this,所以直接用了還是內部的this,而在 testPerson.sayName.call(lily,‘call‘) 和 testPerson.sayName.apply(lily,[‘apply‘])

已經有了外部的lily,所以用了lily對象的this,而不是函數內部的this。因此call和apply是用來改變還是內部this的指向的。

(2)註意一下在用call和apply的時候,這兩個方法接受參數方式的區別

func.call(this, args1, args2,....)

func.apply(this, [args1, args2,...]);

call是將所有參數通過args全部列出來,而apply是將參數存在數組裏,所以在知道函數的參數個數是,二者是沒有什麽區別的。但是如果函數的參數個數不定時,就需要用apply,通過數組的push,將參數傳進數組,然後調用。在參數個數不定的時候,在函數內部也可以通過arguments將這個數組遍歷出來。

bind

關於bind的用法和apply/call 差不多,在MDN上的解釋就是:bind()會創建一個新函數,稱為綁定函數,當調用這個綁定函數時,綁定函數會以創建它時傳入bind()方法的第一個參數作為this,傳入bind()方法的第二個以及以後的參數加上綁定函數運行時本身的參數按照順序作為原函數的參數來調用原函數。

var bar = function(){
console.log(this.x);
}
var foo = {
x:3
};
bar(); //undefined,函數本身和全部作用域中都找不到x,所以輸出undefined
var func = bar.bind(foo);
func(); // 3

在執行bind()創建一個綁定函數之後,在它被執行時,this會被設置成foo,而不是全部作用域。

還有一點需要註意的是,在bind只能執行一次,不能多次執行

var bar = function(){ console.log(this.x); } var foo = { x:3 } var sed = { x:4 } var func = bar.bind(foo).bind(sed); func(); //? var fiv = { x:5 } var func = bar.bind(foo).bind(sed).bind(fiv); 上面這段代碼不會輸出意料中的4,5,而是輸出3,說明多次bind()是無效的。 bind/call/apply區別

function Person(){};
Person.prototype = {
  name:‘John‘,
  sayName:function(type){
    console.log(this.name + " "+ type);
  }
}
var testPerson = new Person();

var lily = {name: ‘lily‘};

testPerson.sayName(‘prototype‘); // John prototype

testPerson.sayName.call(lily,‘call‘); //lily call

testPerson.sayName.apply(lily,[‘apply‘]); // lily apply

testPerson.sayName.bind(lily,[‘bind‘])(); //lily bind

上面的代碼在很容易發現在用bind的時候,後面多了一個(),這個()表示立即執行

說明bind()改變執行上下文之後不是立即執行的,而apply/call是立即執行的。

總結:

  • apply 、 call 、bind 三者都是用來改變函數的this對象的指向的;
  • apply 、 call 、bind 三者第一個參數都是this要指向的對象,也就是想指定的上下文;
  • apply 、 call 、bind 三者都可以利用後續參數傳參;
  • bind 是返回對應函數,便於稍後調用;apply 、call 則是立即調用 。

apply,call,bind的區別