区别: 指定this,call和apply执行函数,bind不执行
call
,apply
,bind
都是为了解决this
的指向,call
和apply
都会执行函数,而bind
只是绑定this
不执行函数。call
和apply
接受参数方式不一样,除了第一个参数都是指定this
,call
接受一个参数列表,apply
只接受一个参数数组。
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)
模拟实现call,apply,bind
实现思路
- 不传入第一个参数,则默认为
window
- 改变this指向,让新的对象可以执行该函数。=》给新的对象添加一个函数,执行之后删除
call
的实现
Function.prototype.myCall = function (context) {
var context = context || window; // 传入的新对象
// 给新对象添加一个属性(方法)
context.fn = this; // this 指向的是调用myCall方法的函数
// 取出剩余参数
var args = [...arguments].slice(1);
var result = context.fn(...args); // 调用context.fn实则调用myCall方法的函数,但函数this指向了context
delete context.fn;
return result
}
apply
的实现
将call
方法实现中参数传递方式改为数组形式
Function.prototype.myApply = function (context) {
var context = context || window; // 传入的新对象
// 给新对象添加一个属性(方法)
context.fn = this; // this 指向的是调用myCall方法的函数
// 剩余参数 数组形式
var result;
if(arguments[1]) {
result = context.fn(...arguments);
} else {
result = context.fn();
}
delete context.fn;
return result
}
bind
的实现
this
指向,返回一个函数
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))
}
}