手写call apply bind

112 阅读1分钟

1、call

// Function.prototype.call(this, arg1, arg2, …..)
// 可以改变this,并且传入参数,立刻执行,返回函数返回值


// Function.prototype.call()样例
function fun(arg1, arg2) {
    console.log(this.name)
    console.log(arg1 + arg2)
}
const obj = { name: '111' }
// 接受的是一个参数列表;方法立即执行
fun.call(obj, 1, 2)



Function.prototype.myCall = function (context = window, ...args) {
    context = context || window; // 参数默认值并不会排除null,所以重新赋值
    context.fn = this; // this是调用call的函数
    const result = context.fn(...args);
    delete context.fn; // 执行后删除新增属性
    return result;
}

fun.myCall(obj, 1, 2)

2、bind

function fun(arg1, arg2) {
    console.log(this.name)
    console.log(arg1 + arg2)
}
const obj = { name: '111' }

Function.prototype.myApply = function (context = window, args = []) {
    context = context || window; // 参数默认值并不会排除null,所以重新赋值
    context.fn = this; // this是调用call的函数
    const result = context.fn(...args);
    delete context.fn;
    return result;
}
fun.myApply(obj, [1, 2])

3、bind

function fun(arg1, arg2) {
    console.log(this.name)
    console.log(arg1 + arg2)
}
const obj = { name: '111' }

Function.prototype.myBind = function (context, ...args) {
    debugger
    const _this = this;
    return function Bind(...newArgs) {
        // 考虑是否此函数被继承
        if (this instanceof Bind) {
            return _this.myApply(this, [...args, ...newArgs])
        }
        return _this.myApply(context, [...args, ...newArgs])
    }
}
fun.myBind(_this, 1, 2)()

手写 bind、call、apply

Function.prototype.MyCall = function (context) {
  const args = [...arguments].slice(1);

  context.fn = this;

  const result = context.fn(...args);
  delete context.fn;

  return result;
}

Function.prototype.MyApply = function (context) {
  const args = arguments[1] || [];

  context.fn = this;
  const result = context.fn(...args);
  delete context.fn;

  return result;
}

Function.prototype.MyBind = function (context) {
  const args = [...arguments].slice(1);

  return function () {
    context.MyApply(context, args);
  }
}