手写 call 、apply、bind方法

call()方法

使用一个指定的 this 值和单独给出的一个或多个参数来调用一个函数

call() 方法接受的是一个参数列表

语法:function.call(thisArg,arg1,arg2,…)

简单来说:call()方法就是用来改变 this 指向的

call 和 apply 实现的思路主要都是:

  • 判断是否是函数调用,若非函数调用抛异常
  • 通过新对象(context)来调用函数
    • 给 context 创建一个 fn 设置为需要调用的函数
    • 结束调用完之后删除 fn
function person(name, age, gender) {
  console.log(this.name);
  console.log(name, age, gender);
}

var jinjianceng = {
  name: "jinjianceng"
}

Function.prototype.myCall = function (context) {
  // 先判断调用 myCall 是不是一个函数
  // 这里的 this 就是调用 mycall 的
  if (typeof this !== "function") {
    throw new TypeError("Not a Function");
  }

  // 不传参数默认为 window
  context = context || window;

  // 保存 this
  // 这里的 this 指向的被绑定的函数
  context.fn = this;

  // 保存参数
  // Array.from 把伪数组对象转为数组
  // slice(1) 的原因是 arguments[0] = this
  let args = Array.from(arguments).slice(1);

  // 调用函数
  // 复制函数
  let result = context.fn(...args);

  // 因为不能改写对象,所以需要把 context.fn 删除掉
  delete context.fn;

  return result;
}

person.myCall(jinjianceng, "jinjianceng", "18", "female") 
// jinjianceng
// jinjianceng 18 female
person.myCall(null, "jinjianceng", "18", "female")
// 
// jinjianceng 18 female

在这里插入图片描述

apply()方法

调用一个具有给定 this 值的函数,以及以一个数组 (或类数组对象)的形式提供参数

apply() 方法接受的是一个参数数组

语法:func.apply(thisArg,[argsArray])

function person(name, age, gender) {
  console.log(this.name);
  console.log(name, age, gender);
}

var jinjianceng = {
  name: "jinjianceng"
}

Function.prototype.myApply = function (context) {
  // 判断 this 是不是函数
  if (typeof this !== "function") {
    throw new TypeError("Not a Function");
  }

  let result;

  // 默认没有 this 时是window
  context = context || window;

  // 保存 this
  context.fn = this;

  // 是否传参
  if (arguments[1]) {
    result = context.fn(...arguments[1]);
  } else {
    result = context.fn();
  }

  delete context.fn;

  return result;
}

person.myApply(jinjianceng, ["jinjianceng", "18", "female"]) 
// jinjianceng
// jinjianceng 18 female
person.myApply(null, ["jinjianceng", "18", "female"])
// 
// jinjianceng 18 female

在这里插入图片描述

bind()方法

创建一个新的函数,在 bind() 被调用后,这个新函数的 this 被指定为 bind() 的第一个参数,而其余参数将作为新函数的参数,供调用时使用

语法:function.bind(thisArg[,arg1[,arg2[,…]]])

function person(name, age, gender) {
  console.log(this.name);
  console.log(name, age, gender);
}

var jinjianceng = {
  name: "jinjianceng"
}

Function.prototype.myBind = function (context) {
  // 判断是否是一个函数
  if (typeof this !== "function") {
    throw new TypeError("Not a Function");
  }

  // 保存调用 bind 的函数
  const _this = this;

  // 保存参数
  const args = Array.prototype.slice.call(arguments, 1);

  // 返回一个函数
  return function F() {
    if (this instanceof F) {
      // 判断是不是 new 出来的
      // 返回一个空对象,且使创建出来的实例的 __proto__ 指向 _this 的 prototype,且完成函数柯里化
      return new _this(...args, ...arguments);
    } else {
      // 如果不是 new 出来的改变 this 指向,且完成函数柯里化
      return _this.apply(context, args.concat(...arguments));
    }
  }
}

person.myBind(jinjianceng, "jinjianceng", "18")("female")
// "jinjianceng"
// "jinjianceng" "18" "female"
person.myBind(null, "jinjianceng", "18")("female")
// 
// jinjianceng 18 female

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值