apply,call,bine 這三兄弟經(jīng)常讓初學(xué)者感到疑惑。前兩天準(zhǔn)備面試時特地做了個比較窘拯,其實(shí)理解起來也不會太難红且。
apply
MDN上的定義:
The apply() method calls a function with a given this value and arguments provided as an array (or an array-like object).
apply() 方法調(diào)用一個函數(shù),指定該函數(shù)的 this 值并將一個數(shù)組(或類數(shù)組對象)作為該函數(shù)的參數(shù)涤姊。
語法 (Syntax)
fun.apply(thisArg,[argsArray])
直接上代碼
function sayColor(arg) {
var color = "red";
console.log(arg + this.color);
}
var obj = {color: "blue"};
sayColor.apply(obj, ["The color is"]); //輸出"The color is blue"
此時 this 指向 obj 暇番,則 this.color 為 obj 的 color 屬性,則輸出 The color is blue思喊。
call
call()
與 apply()
類似壁酬,區(qū)別在于 apply()
的第二個參數(shù)為數(shù)組,而 call()
把參數(shù)跟在第一個參數(shù)后面恨课,并且可以跟多個參數(shù)舆乔。
語法 (Syntax)
fun.call(thisArg, arg1, arg2, arg3 ...)
看代碼
function sayClothe(arg1,arg2) {
console.log(arg1 + this.color + arg2);
}
var obj = {color: "blue"};
sayClothe.call(obj, "This is a ", " clothe" ); //輸出"This is a blue clothe"
bind
bind()
與 call()
類似,有一點(diǎn)不同在于 bind()
返回一個新函數(shù)(new function)剂公,我們可以隨時調(diào)用該函數(shù)希俩。
語法(Syntax)
fun.bind(thisArg, arg1, arg2, arg3 ...)
返回值
返回一個具有指定 this
和初始參數(shù)的函數(shù)副本。
看代碼
function sayClothe(arg1, arg2) {
console.log(arg1 + this.color + arg2);
}
var obj = {color: "blue"};
var sayClothe2 = sayClothe.bind(obj, "This is a ", " clothe");
sayClothe2(); //輸出 "This is a blue clothe"
使用
有時候我們會碰到 Array.prototype.slice.call(arguments)
這種用法纲辽。許多人會疑惑颜武,直接使用 arguments.slice()
不就行了嗎璃搜,為什么要多此一舉。
原因在于盒刚,arguments 并不是真正的數(shù)組對象腺劣,只是 array-like object ,所以它并沒有 slice 這個方法因块。而 Array.prototype.slice.call(arguments)
可以理解為把 slice 的對象指向 arguments ,從而讓 arguments 可以使用 slice 方法橘原。如果直接使用 arguments.slice()
則會報錯。
bind()
的另一個用法則是讓函數(shù)擁有預(yù)設(shè)參數(shù)涡上,而又跟預(yù)設(shè)參數(shù)有所不同趾断。
以下例子結(jié)合上面兩條規(guī)則 本例出自MDN
function list() {
return Array.prototype.slice.call(arguments);
}
var list1 = list(1, 2, 3); //[1, 2, 3]
//Create a function with a preset leading arguments
var leadingThirtysevenList = list.bind(null, 37);
var list2 = leadingThirtysevenList();
//[37]
var list3 = leadingThirtysevenList(1, 2, 3);
//[37, 1, 2, 3]
我們想到預(yù)設(shè)參數(shù)就會理所當(dāng)然的想到 “如果該函數(shù)沒有參數(shù)就使用預(yù)設(shè)參數(shù),有參數(shù)就使用提供的參數(shù)”吩愧。不過 bind()
所提供的預(yù)設(shè)參數(shù)功能與此不同芋酌。
在我們的印象中, list3
應(yīng)該輸出 [1, 2, 3]
但實(shí)際輸出的卻是 [37, 1, 2, 3]
雁佳。因?yàn)?bind()
的特點(diǎn)脐帝,leadingThirtysevenList(1, 2, 3)
可以寫為 list.bind(null, 37, 1, 2, 3)
。
總結(jié)
apply() call() bind()
三者區(qū)別不大糖权,都是用來改變函數(shù)的 this 指向堵腹。
apply()
把 this 所需參數(shù)放入一個數(shù)組,作為 apply()
的第二個參數(shù)傳入星澳。當(dāng)參數(shù)不定時疚顷,我們可以傳入 arguments。 call()
和 bind()
則把參數(shù)按順序依次傳入禁偎。
bind()
返回對應(yīng)函數(shù)腿堤,便于稍后調(diào)用,而 apply()
如暖、call()
則立即調(diào)用
由于其特性笆檀,使用起來千奇百怪,有各種各樣有趣的用法装处,還等待我們?nèi)ネ诰颉?/p>