bind,call,apply模拟实现

发布于:2023-05-25 ⋅ 阅读:(105) ⋅ 点赞:(0)

首先,三者第一个参数都为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;
}