區(qū)別: 指定this芥吟,call和apply執(zhí)行函數(shù),bind不執(zhí)行
call
专甩,apply
钟鸵,bind
都是為了解決this
的指向,call
和apply
都會(huì)執(zhí)行函數(shù)涤躲,而bind
只是綁定this
不執(zhí)行函數(shù)棺耍。call
和apply
接受參數(shù)方式不一樣,除了第一個(gè)參數(shù)都是指定this
篓叶,call
接受一個(gè)參數(shù)列表烈掠,apply
只接受一個(gè)參數(shù)數(shù)組。
var obj = {
value: 1
}
function foo(a, b) {
console.log(a, b)
console.log(this.value)
}
foo.call(obj, 1, 2)
foo.apply(obj, [1, 2])
// bind 只綁定
foo.bind(obj, 1, 2)
模擬實(shí)現(xiàn)call缸托,apply左敌,bind
實(shí)現(xiàn)思路
- 不傳入第一個(gè)參數(shù),則默認(rèn)為
window
- 改變this指向俐镐,讓新的對(duì)象可以執(zhí)行該函數(shù)矫限。=》給新的對(duì)象添加一個(gè)函數(shù),執(zhí)行之后刪除
call
的實(shí)現(xiàn)
Function.prototype.myCall = function (context) {
var context = context || window; // 傳入的新對(duì)象
// 給新對(duì)象添加一個(gè)屬性(方法)
context.fn = this; // this 指向的是調(diào)用myCall方法的函數(shù)
// 取出剩余參數(shù)
var args = [...arguments].slice(1);
var result = context.fn(...args); // 調(diào)用context.fn實(shí)則調(diào)用myCall方法的函數(shù)佩抹,但函數(shù)this指向了context
delete context.fn;
return result
}
apply
的實(shí)現(xiàn)
將call
方法實(shí)現(xiàn)中參數(shù)傳遞方式改為數(shù)組形式
Function.prototype.myApply = function (context) {
var context = context || window; // 傳入的新對(duì)象
// 給新對(duì)象添加一個(gè)屬性(方法)
context.fn = this; // this 指向的是調(diào)用myCall方法的函數(shù)
// 剩余參數(shù) 數(shù)組形式
var result;
if(arguments[1]) {
result = context.fn(...arguments);
} else {
result = context.fn();
}
delete context.fn;
return result
}
bind
的實(shí)現(xiàn)
this
指向叼风,返回一個(gè)函數(shù)
Function.prototype.myBind = function (context) {
var context = context || window;
var _this = this;
var args = [...arguments].slice(1);
return function () {
_this.apply(context, args.concat(...arguments))
}
}