JavaScript中的call(), apply()和bind()是Function.prototype下的方法畦木,都是用于改變函數(shù)運(yùn)行時(shí)上下文兜粘,最終的返回值是你調(diào)用的方法的返回值申窘,若該方法沒有返回值,則返回undefined孔轴。這幾個(gè)方法很好地體現(xiàn)了js函數(shù)式語(yǔ)言特性剃法,在js中幾乎每一次編寫函數(shù)式語(yǔ)言風(fēng)格的代碼,都離不開call和apply路鹰。
1. call()
-
描述:
call()
方法使用一個(gè)指定的this
值和單獨(dú)給出的一個(gè)或多個(gè)參數(shù)來(lái)調(diào)用一個(gè)函數(shù)玄窝。
call()
允許為不同的對(duì)象分配和調(diào)用屬于一個(gè)對(duì)象的函數(shù)/方法。
call()
提供新的 this 值給當(dāng)前調(diào)用的函數(shù)/方法悍引。你可以使用 call 來(lái)實(shí)現(xiàn)繼承:寫一個(gè)方法,然后讓另外一個(gè)新的對(duì)象來(lái)繼承它(而不是在新對(duì)象中再寫一次這個(gè)方法)帽氓。 - 語(yǔ)法:
function.call(thisArg, arg1, arg2, ...)
-
參數(shù):
thisArg
在function
函數(shù)運(yùn)行時(shí)指定的this
值趣斤。需要注意的是,指定的this
值并不一定是該函數(shù)執(zhí)行時(shí)真正的this
值黎休,如果這個(gè)函數(shù)在[非嚴(yán)格模式
]下運(yùn)行浓领,則指定為null
和undefined
的this
值會(huì)自動(dòng)指向全局對(duì)象(瀏覽器中就是 window 對(duì)象),同時(shí)值為原始值(數(shù)字势腮,字符串联贩,布爾值)的this
會(huì)指向該原始值的自動(dòng)包裝對(duì)象。
arg1, arg2, ...
指定的參數(shù)列表捎拯。 -
返回值:
使用調(diào)用者提供的 this 值和參數(shù)調(diào)用該函數(shù)的返回值泪幌。若該方法沒有返回值,則返回 undefined署照。 - 示例:
function Product(name, price) {
this.name = name;
this.price = price;
}
function Food(name, price) {
Product.call(this, name, price);
this.category = 'food';
}
console.log(new Food('cheese', 5).name);
// expected output: "cheese"
2. apply()
-
描述
apply()
方法調(diào)用一個(gè)具有給定this
值的函數(shù)祸泪,以及作為一個(gè)數(shù)組(或類似數(shù)組對(duì)象)提供的參數(shù)。
在調(diào)用一個(gè)存在的函數(shù)時(shí)建芙,你可以為其制定一個(gè)this
對(duì)象没隘,this
指當(dāng)前對(duì)象,也就是正在調(diào)用這個(gè)函數(shù)的對(duì)象禁荸。使用apply
右蒲,你可以只寫一次這個(gè)方法然后在另一個(gè)對(duì)象中繼承它阀湿,而不用在新對(duì)象中重復(fù)寫該方法。
apply
與call()
非常相似瑰妄,不同之處在于提供參數(shù)的方式陷嘴。apply
使用參數(shù)數(shù)組而不是一組參數(shù)列表。apply
可以使用數(shù)組字面量(array literal)翰撑,如fun.apply(this, ['eat', 'bananas'])
罩旋,或數(shù)組對(duì)象, 如fun.apply(this, new Array('eat', 'bananas'))
眶诈。
你也可以使用arguments
對(duì)象作為argsArray
參數(shù)涨醋。arguments
是一個(gè)函數(shù)的局部變量。 它可以被用作被調(diào)用對(duì)象的所有未指定的參數(shù)逝撬。 這樣浴骂,你在使用apply函數(shù)的時(shí)候就不需要知道被調(diào)用對(duì)象的所有參數(shù)。 你可以使用arguments來(lái)把所有的參數(shù)傳遞給被調(diào)用對(duì)象宪潮。 被調(diào)用對(duì)象接下來(lái)就負(fù)責(zé)處理這些參數(shù)溯警。
從 ECMAScript 第5版開始,可以使用任何種類的類數(shù)組對(duì)象狡相,就是說(shuō)只要有一個(gè)length
屬性和(0..length-1)
范圍的整數(shù)屬性梯轻。例如現(xiàn)在可以使用NodeList
或一個(gè)自己定義的類似{'length': 2, '0': 'eat', '1': 'bananas'}
形式的對(duì)象。
需要注意:Chrome 14 以及 Internet Explorer 9 仍然不接受類數(shù)組對(duì)象尽棕。如果傳入類數(shù)組對(duì)象喳挑,它們會(huì)拋出異常。
- 語(yǔ)法
function.apply(thisArg, [argsArray])
-
參數(shù)
thisArg
可選的滔悉。在function
函數(shù)運(yùn)行時(shí)使用的this
值伊诵。請(qǐng)注意,this
可能不是該方法看到的實(shí)際值:如果這個(gè)函數(shù)處于非嚴(yán)格模式下回官,則指定為null
或undefined
時(shí)會(huì)自動(dòng)替換為指向全局對(duì)象曹宴,原始值會(huì)被包裝。
argsArray
可選的歉提。一個(gè)數(shù)組或者類數(shù)組對(duì)象笛坦,其中的數(shù)組元素將作為單獨(dú)的參數(shù)傳給function
函數(shù)。如果改參數(shù)的值為null
或undefined
苔巨,則表示不需要傳入任何參數(shù)弯屈。從ECMAScript 5 開始可以使用類數(shù)組對(duì)象。 -
返回值
調(diào)用有指定this
值和參數(shù)的函數(shù)的結(jié)果恋拷。 - 示例
var numbers = [5, 6, 2, 3, 7];
var max = Math.max.apply(null, numbers);
console.log(max);
// expected output: 7
var min = Math.min.apply(null, numbers);
console.log(min);
// expected output: 2
3. bind()
-
描述
bind()
方法創(chuàng)建一個(gè)新的函數(shù)资厉,在調(diào)用時(shí)設(shè)置this關(guān)鍵字為提供的值。并在調(diào)用新函數(shù)時(shí)蔬顾,將給定參數(shù)列表作為原函數(shù)的參數(shù)序列的前若干項(xiàng)宴偿。
bind()
函數(shù)會(huì)創(chuàng)建一個(gè)新綁定函數(shù)(bound function湘捎,BF)
。綁定函數(shù)是一個(gè)exotic function object
(怪異函數(shù)對(duì)象窄刘,ECMAScript 2015中的術(shù)語(yǔ))窥妇,它包裝了原函數(shù)對(duì)象。調(diào)用綁定函數(shù)
通常會(huì)導(dǎo)致執(zhí)行包裝函數(shù)
娩践。
綁定函數(shù)
具有以下內(nèi)部屬性:
[[BoundTargetFunction]]
- 包裝的函數(shù)對(duì)象
[[BoundThis]]
- 在調(diào)用包裝函數(shù)時(shí)始終作為this
值傳遞的值活翩。
[[BoundArguments]]
- 列表,在對(duì)包裝函數(shù)做任何調(diào)用都會(huì)優(yōu)先用列表元素填充參數(shù)列表翻伺。
[[Call]]
- 執(zhí)行與此對(duì)象關(guān)聯(lián)的代碼材泄。通過(guò)函數(shù)調(diào)用表達(dá)式調(diào)用。內(nèi)部方法的參數(shù)是一個(gè)this值和一個(gè)包含通過(guò)調(diào)用表達(dá)式傳遞給函數(shù)的參數(shù)的列表吨岭。
當(dāng)調(diào)用綁定函數(shù)時(shí)拉宗,它調(diào)用[[BoundTargetFunction]]
上的內(nèi)部方法[[Call]]
,就像這樣Call(boundThis, args)
辣辫。其中旦事,boundThis
是[[BoundThis]]
,args
是[[BoundArguments]]
加上通過(guò)函數(shù)調(diào)用傳入的參數(shù)列表急灭。
綁定函數(shù)也可以使用new
運(yùn)算符構(gòu)造姐浮,它會(huì)表現(xiàn)為目標(biāo)函數(shù)已經(jīng)被構(gòu)建完畢了似的。提供的this
值會(huì)被忽略葬馋,但前置參數(shù)仍會(huì)提供給模擬函數(shù)卖鲤。 - 語(yǔ)法
function.bind(thisArg[, arg1[, arg2[, ...]]])
-
參數(shù)
thisArg
調(diào)用綁定函數(shù)時(shí)作為this
參數(shù)傳遞給目標(biāo)函數(shù)的值。 如果使用new
運(yùn)算符構(gòu)造綁定函數(shù)点楼,則忽略該值。當(dāng)使用bind
在setTimeout
中創(chuàng)建一個(gè)函數(shù)(作為回調(diào)提供)時(shí)白对,作為thisArg
傳遞的任何原始值都將轉(zhuǎn)換為object
掠廓。如果bind
函數(shù)的參數(shù)列表為空,執(zhí)行作用域的this
將被視為新函數(shù)的thisArg
甩恼。
arg1, arg2, ...
當(dāng)目標(biāo)函數(shù)被調(diào)用時(shí)蟀瞧,預(yù)先添加到綁定函數(shù)的參數(shù)列表中的參數(shù)。 -
返回值
返回一個(gè)原函數(shù)的拷貝条摸,并擁有指定的this
值和初始參數(shù)悦污。 - 示例
var module = {
x: 42,
getX: function() {
return this.x;
}
}
var unboundGetX = module.getX;
console.log(unboundGetX()); // The function gets invoked at the global scope
// expected output: undefined
var boundGetX = unboundGetX.bind(module);
console.log(boundGetX());
// expected output: 42