從一開始,我是在書上看到關于bind()、call() 和 apply(), 不過長久以來,在工作中與網(wǎng)上接觸到了很多關于這三個方法的使用場景,對這三個方法也算是比較熟悉了。所以把他們的作用和區(qū)別簡單闡述一下!
javaScript權威指南上的解釋是: call() 、apply()可以看作是某個對象的方法,通過調(diào)用方法的形式來間接調(diào)用函數(shù)。bind() 就是將某個函數(shù)綁定到某個對象上。也叫綁定函數(shù)
關于call() 和 apply() 在犀牛書上的解釋可能比較生澀難懂,我的理解就是,它們的作用是: 讓函數(shù)在某個指定的對象下執(zhí)行。
例:
var obj = {x: 1}
function foo() {console.log(this.x)}
foo.call(obj) //打印結果: 1
call() 和apply()的第一個參數(shù)相同,就是指定的對象。這個對象就是該函數(shù)的執(zhí)行上下文。
call()和apply()的區(qū)別就在于,兩者之間的參數(shù)。
call()在第一個參數(shù)之后的 后續(xù)所有參數(shù)就是傳入該函數(shù)的值。apply() 只有兩個參數(shù),第一個是對象,第二個是數(shù)組就是該組,這個數(shù)組就是該函數(shù)的參數(shù)。
例1:
var obj = {};
function foo(a, b, c) {
console.log(b);
}
foo.call(obj, 1, 2, 3) //打印結果: 2;
例2:
var obj = {};
function foo(a, b, c) {
console.log(b);
}
foo.apply(obj, [1, 2, 3]) 打印結果: 2;
bind() 方法和前兩者不同在于: bind() 方法會返回執(zhí)行上下文被改變的函數(shù)而不會立即執(zhí)行,而前兩者是直接執(zhí)行該函數(shù)。他的參數(shù)和call()相同。
這三個方法的作用都是改變函數(shù)的執(zhí)行上下文!
實現(xiàn)一個簡單的bind函數(shù)
Function.prototype.bind = function() {
var self = this;
context = [].shift.call(arguments) // 需要綁定的this上下文
args = [].slice.call(arguments) //剩余的參數(shù)轉成數(shù)組
return function(){ // 返回一個新的函數(shù)
return selft.applay(context,[].concat.call(args,[].slice.call(arguments));
//執(zhí)行新的函數(shù)的時候,會把之前傳入的context當做新函數(shù)體內(nèi)的this
//并且組合兩次分別傳入的參數(shù),作為新函數(shù)的參數(shù)
}
}
call,apply,bind的區(qū)別
相同點:都是為了改變this指向
call和apply會立即執(zhí)行,bind不會
call:接收一個或多個參數(shù)
接受一個或多個時,第一個參數(shù)永遠改變原函數(shù)的this指向,第一個參數(shù)如果是null和undefined時,this指向window
后面的所有參數(shù),會覆蓋原函數(shù)的參數(shù)
apply:接收一個或兩個參數(shù)
接受一個或兩個時,第一個參數(shù)永遠改變原函數(shù)的this指向
第二個參數(shù),必須是數(shù)組,這個數(shù)組會覆蓋原函數(shù)的所有參數(shù)(arguments)
bind方法,他是直接改變這個函數(shù)的this指向并且返回一個新的函數(shù),之后再次調(diào)用這個函數(shù)的時候this都是指向bind綁定的第一個參數(shù)