一、相似點(diǎn)
apply、call和bind
都是Function類(lèi)下prototype的共有函數(shù),即所有函數(shù)都有。
都是用于指定 調(diào)用該方法(apply、call和bind)的 函數(shù)(fn) 執(zhí)行的作用域
二、用法及區(qū)別
1. apply
color ='blue';
var obj = {color :'red'};
function fn(){
console.log(this.color);
}
fn();
fn.apply(obj);
輸出結(jié)果
blue
red
兩種調(diào)用方式,fn()的作用域?yàn)槿?,因此輸出結(jié)果為blue
fn.apply(obj) 通過(guò)apply將fn執(zhí)行的作用域指定為obj,其執(zhí)行效果等同于
var obj = {
color :'red',
b:function fn(){
console.log(this.color);
}
};
obj.b();
2. call
在介紹call之前,再看一個(gè)apply的例子
function sum(a,b){
return a + b;
}
function callSumWithApply(a,b) {
return sum.apply(this,[a,b]);
}
function callSumWithCall(a,b){
return sum.call(this,a,b);
}
console.log(callSumWithApply(1,2));
console.log(callSumWithCall(3,4));
輸出結(jié)果:
3
7
解析:
sum.apply(this,[a,b])
通過(guò)apply指定sum的執(zhí)行作用域?yàn)槿?,通過(guò)數(shù)組傳入?yún)?shù)列表,在sum執(zhí)行時(shí)再拆分?jǐn)?shù)組與參數(shù)順序一一對(duì)應(yīng)。(劃重點(diǎn)1)
sum.call(this,a,b)
通過(guò)call指定sum的執(zhí)行作用域?yàn)槿郑苯訉⒑瘮?shù)參數(shù)依次填入,傳入?yún)?shù)列表。call和apply的差異僅此而已。 (傳參差異)
3. bind
apply和call在調(diào)用后立即執(zhí)行,而bind會(huì)創(chuàng)建一個(gè)函數(shù)的實(shí)例,其this值會(huì)被綁定到傳給bind()函數(shù)的值,該實(shí)例被調(diào)用后才執(zhí)行。
color ='red';
var p = {color:'blue'};
function colorOut() {
console.log(this.color);
}
var colorBind = colorOut.bind(p);
colorBind();
colorOut();
輸出結(jié)果:
blue
red
三、一些算法巧解
將兩個(gè)數(shù)組元素合并,常規(guī)做法是:
var arrayA = ['q','w'];
var arrayB = [1,2];
var arrayC =arrayA.concat(arrayB);
console.log(arrayA,arrayB,arrayC);
輸出結(jié)果:[ 'q', 'w' ] [ 1, 2 ] [ 'q', 'w', 1, 2 ]
但原數(shù)組并沒(méi)有變,必須新建數(shù)組才能囊括二者。如果直接向數(shù)組arrayA中push數(shù)組arrayB,即:
arrayA.push(arrayB);
輸出結(jié)果:[ 'q', 'w', [ 1, 2 ] ]
因?yàn)檎{(diào)用push時(shí),是按參數(shù)項(xiàng)直接添加的,arrayB被當(dāng)做一個(gè)元素直接添加到數(shù)組中,出現(xiàn)數(shù)組中的數(shù)組,事與愿違。我們期望的方式是:
arrayA.push(1,2);
因此,可以借助apply方法(在二.2中 劃重點(diǎn)1處 有如下說(shuō)明 apply 通過(guò)數(shù)組傳入?yún)?shù)列表,在sum執(zhí)行時(shí)再拆分?jǐn)?shù)組與參數(shù)順序一一對(duì)應(yīng)):
arrayA.push.apply(arrayA,arrayB);
先指定push函數(shù)的的作用域?yàn)閷?duì)象arrayA,然后將數(shù)組arrayB當(dāng)做參數(shù)列表傳入?yún)?shù)
輸出結(jié)果為:[ 'q', 'w', 1, 2 ]
如前所述,如果調(diào)用call方法,則直接會(huì)把a(bǔ)rrayB當(dāng)做參數(shù)傳遞.
arrayA.push.call(arrayA,arrayB);
輸出結(jié)果[ 'q', 'w', [ 1, 2 ] ]
最后補(bǔ)充一下:
arrayA.push.apply(arrayA,arrayB);
第一個(gè)arrayA其實(shí)換成arrayB或者arrayC都是可行的,甚至用
[].push.apply(arrayA,arrayB)
也是沒(méi)問(wèn)題的。因?yàn)槲覀円氖莗ush方法,后面已經(jīng)通過(guò)apply指定了該push方法的作用域,因此這個(gè)push原本屬于哪個(gè)數(shù)組已經(jīng)不重要了