首先,三者第一个参数都为this指向
区别
bind返回的是一个函数体
call和apply会直接执行,但是call参数需要一个一个进行传递,apply的第二个参数是一个数组
实现
bind
简单实现
Function.prototype.myBind = function(context){
self = this; //保存this,即调用bind方法的目标函数
return function(){
return self.applay(context, [...arguments]);
};
};
考虑到函数柯里化的实现
Function.prototype.myBind = function(context){
// 使用闭包存下初始参数
var args = Array.prototype.slice.call(arguments, 1),
self = this;
return function() {
// 再次调用时
var innerArgs = Array.prototype.slice.call(arguments);
var finalArgs = args.concat(innerArgs);
return self.apply(context,finalArgs);
};
};
考虑构造函数的实现
Function.prototype.myBind = function(context){
// 判断是否为函数
if(typeof this !== 'function') {
throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable');
}
var args = Array.prototype.slice(arguments, 1);
self = this;
bound = function() {
var innerArgs = Array.prototype.slice.call(arguments);
var finalArgs = args.concat(innerArgs);
// 判断this,如果是,则传递this即实例化的对象。
return self.apply((this instanceof F ? this : context), finalArgs);
};
// 处理原型链
let F = function(){};
F.prototype = self.prototype;
bound.prototype = new F();
retrun bound;
};
call
思路
// 要实现这个效果
var foo ={
value:1
}
function bar(){
console.log(this.value)
}
bar.call(foo);//1
// 相当于做如下事情
var foo = {
value: 1,
bar: function() {
console.log(this.value)
}
};
foo.bar(); // 1
实现
Function.Prototype.myCall = function(context) {
// this 参数可以传 null,当为 null 的时候,视为指向 window
var context = context || window;
context.fn = this;
// 对参数进行处理
var args = [];
for(var i = 1, len = arguments.length; i < len; i++) {
args.push(arguments[i]);
}
let result = arguments.length>0 ? context.fn(...args) : context.fn();
delete context.fn;
return result;
}
apply
Function.Prototype.myApply = function(context, arr) {
// this 参数可以传 null,当为 null 的时候,视为指向 window
var context = context || window;
context.fn = this;
let result = arr.length>0 ? context.fn(...arr) : context.fn();
delete context.fn;
return result;
}