一、常規
在 JavaScript 中,apply、call、bind 是三個與函式呼叫相關的方法,它們都允許你在呼叫函式時手動設定函式的背景關系(即 this 指向),
1、apply 方法:apply 方法允許你呼叫一個函式,并且手動設定函式的背景關系(即 this 指向)以及傳遞一個引數陣列,其語法如下:
function.apply(thisArg, [argsArray])
其中,thisArg 表示函式要系結的背景關系,argsArray 是一個可選的陣列,其中包含將傳遞給函式的引數串列,
例如,以下代碼會將陣列 [1, 2, 3] 作為引數傳遞給函式 foo,并且將函式的背景關系設定為物件 obj:
function foo(a, b, c) {
console.log(a + b + c);
}
var obj = {
x: 1,
y: 2,
z: 3
};
foo.apply(obj, [1, 2, 3]); // 輸出 6
2、call 方法:call 方法與 apply 方法類似,也是允許你呼叫一個函式,并且手動設定函式的背景關系(即 this 指向),但是它需要你手動傳遞一個引數串列,而不是一個引數陣列,其語法如下:
function.call(thisArg, arg1, arg2, ...)
其中,thisArg 表示函式要系結的背景關系,arg1、arg2、... 是將傳遞給函式的引數串列,
例如,以下代碼會將引數 1、2、3 傳遞給函式 foo,并且將函式的背景關系設定為物件 obj:
function foo(a, b, c) {
console.log(a + b + c);
}
var obj = {
x: 1,
y: 2,
z: 3
};
foo.call(obj, 1, 2, 3); // 輸出 6
3、bind 方法:bind 方法與 apply、call 方法不同,它并不會立即呼叫函式,而是會回傳一個新的函式,并且這個新函式的背景關系(即 this 指向)被永久地系結到了指定的物件上,其語法如下:
function.bind(thisArg, arg1, arg2, ...)
其中,thisArg 表示函式要系結的背景關系,arg1、arg2、... 是一些可選的引數,這些引數將在呼叫新函式時作為引數串列傳遞給原函式,
例如,以下代碼會將函式 foo 的背景關系系結到物件 obj 上,并回傳一個新函式 newFoo,當呼叫 newFoo 時,它的引數將被傳遞給原函式 foo:
function foo(a, b, c) {
console.log(a + b + c + this.x + this.y + this.z);
}
var obj = {
x: 1,
y: 2,
z: 3
};
var newFoo = foo.bind(obj, 1, 2, 3);
newFoo(); // 輸出 12
下面是一個示例,演示了使用 apply、call、bind 方法的一些特性:
function foo(a, b) {
console.log(this.x + this.y + a + b);
}
var obj1 = {
x: 1,
y: 2
};
var obj2 = {
x: 3,
y: 4
};
// 使用 apply 方法呼叫函式 foo,并將 obj1 作為背景關系
foo.apply(obj1, [3, 4]); // 輸出 10
// 使用 call 方法呼叫函式 foo,并將 obj2 作為背景關系
foo.call(obj2, 5, 6); // 輸出 18
// 使用 bind 方法系結函式 foo 的背景關系為 obj1,并創建一個新函式 newFoo
var newFoo = foo.bind(obj1, 7);
newFoo(8); // 輸出 18
// 使用 bind 方法系結函式 foo 的背景關系為 obj2,并創建一個新函式 newFoo2
var newFoo2 = foo.bind(obj2);
newFoo2(9, 10); // 輸出 26
二、特殊
1、如果在使用 apply、call、bind 方法時沒有傳遞 thisArg 引數或者傳遞了 null 或 undefined,那么默認的背景關系將是全域物件(在瀏覽器環境中,通常是 window 物件),
function foo() {
console.log(this === window); // 在瀏覽器環境中,輸出 true
}
// 使用 apply 方法呼叫函式 foo,沒有傳遞 thisArg 引數
foo.apply(); // 輸出 true
// 使用 call 方法呼叫函式 foo,傳遞了 null 作為 thisArg 引數
foo.call(null); // 輸出 true
// 使用 bind 方法系結函式 foo 的背景關系為 null,并創建一個新函式 newFoo
var newFoo = foo.bind(null);
newFoo(); // 輸出 true
2、如果使用 bind 方法系結了函式的背景關系后,再使用 apply 或 call 方法呼叫這個函式,那么系結的背景關系將會被忽略,仍然使用傳遞給 bind 方法的背景關系,
var obj1 = {
x: 1,
y: 2
};
var obj2 = {
x: 3,
y: 4
};
function foo() {
console.log(this.x + this.y);
}
// 使用 bind 方法系結函式 foo 的背景關系為 obj1,并創建一個新函式 newFoo
var newFoo = foo.bind(obj1);
// 使用 apply 方法呼叫新函式 newFoo,并將 obj2 作為背景關系
newFoo.apply(obj2); // 輸出 3
// 使用 call 方法呼叫新函式 newFoo,并將 obj2 作為背景關系
newFoo.call(obj2); // 輸出 3
在這個示例中,先使用 bind 方法將函式 foo 的背景關系系結為 obj1,并創建了一個新函式 newFoo,然后,分別使用 apply 和 call 方法呼叫新函式 newFoo,并將 obj2 作為背景關系,由于使用了 bind 方法系結了背景關系,無論傳遞了什么引數,都不會改變系結的背景關系,這就是系結的背景關系被忽略的情況,最終輸出的結果為 3,而不是 7,
3、如果使用 bind 方法系結了函式的背景關系后,再使用 new 運算子創建實體,那么系結的背景關系將被忽略,而是創建一個新的物件作為 this,并且原函式中的 this 將會指向這個新物件,
function Foo() {
this.x = 1;
this.y = 2;
}
var obj = {
x: 3,
y: 4
};
// 使用 bind 方法系結函式 Foo 的背景關系為 obj,并創建一個新函式 NewFoo
var NewFoo = Foo.bind(obj);
// 使用 new 運算子創建實體,此時會忽略系結的背景關系 obj,而是創建一個新物件作為 this
var newObj = new NewFoo();
console.log(newObj.x); // 輸出 1
console.log(newObj.y); // 輸出 2
console.log(obj.x); // 輸出 3
console.log(obj.y); // 輸出 4
在這個示例中,先使用 bind 方法將函式 Foo 的背景關系系結為 obj,并創建了一個新函式 NewFoo,然后,使用 new 運算子創建實體,此時會忽略系結的背景關系 obj,而是創建一個新物件作為 this,因此,實體 newObj 中繼承了系結函式 Foo 中定義的屬性 x 和 y,輸出 1 和 2,同時,原函式中的 this 指向了新創建的物件 newObj,因此在原函式中定義的屬性 x 和 y 也被添加到了新物件上,
綜上所述,apply、call、bind 方法都是用于手動設定函式的背景關系(即 this 指向),在實際開發中也經常被使用,對于這三個方法,需要了解它們的使用方法、語法和一些注意事項,以便在開發中更加靈活地使用它們,
作者:飛仔FeiZai
出處:https://www.cnblogs.com/yuzhihui/p/17147218.html
宣告:歡迎任何形式的轉載,但請務必注明出處!!!
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/544887.html
標籤:其他
