一.call和apply
call和apply其實是同一個東西,區別只有參數不同,call是apply的語法糖,所以就放在一起說了,這兩個方法都是定義在函數對象的原型上的(Function.prototype),call和apply方法的作用都是改變函數的執行環境,第一個參數傳入上下文執行環境,然后傳入函數執行所需的參數。傳入call的參數只能是單個參數,不能是數組。apply可傳入數組。話不多說直接上代碼,看下面的例子:
1.
function ga() {
let x=1;
function gb(y) {
return x+y;
}
}
gb(2) //調用發生報錯,因為拿不到x的值
gb.call(ga,2); //使gb在ga環境中執行,可以拿到x,運行正常
上面的代碼中由於gb()函數執行依賴於ga()中的變量,所以我們使用了call將gb的運行環境變成了ga。
2.
function gg(x,y,z){
let a=Array.prototype.slice.call(arguments,1,2) //通過slice方法獲取到了第二個參數
return a; //返回[2]
}
gg(1,2,3)
arguments是一個類數組對象,它本身不能調用數組的slice方法,使用call將執行slice方法的對象由數組變為了arguments。
3.
我們可以使用apply來改寫上面的代碼,傳入一個數組。
function gg(x,y,z){
let d=[1,2]
let a=Array.prototype.slice.apply(arguments,d) //通過slice方法獲取到了第二個參數
return a; //返回[2]
}
gg(1,2,3)
4.
我們還可以使用apply和call實現繼承。
function Parent(name)
{
this.name = name;
this.sayHello = function()
{
alert(name);
}
}
function Child(name)
{
//子類的this傳給父類
Parent.call(this, name);
}
var parent = new Parent("張三");
var child = new Child("李四");
parent.sayHello();
child.sayHello();
二. bind
bind和apply區別是apply會立刻執行,而bind只是起一個綁定執行上下文的作用。看下面的例子:
function ga() {
let x=1;
(function gb(y) {
return x+y;
}).bind(this) //使用bind將gb函數的執行上下文綁定到ga上
}
gb(2) //運行正常,得到3
有些情況下為了方便我們可以直接將ga綁定,而不用在調用的時候再使用apply。