JS修改this指向:call、apply和bind函数

本文详细解析了JavaScript中this关键字的作用域问题,并介绍了如何通过call、apply及bind方法来改变函数内部this的指向。同时提供了这些方法的具体实现代码。

call 函数

语法

obj.call(thisObj,arg[,arg2[,arg3[,...agr]]]);

简介

修改obj的this指向为thisObj,后面的参数会当成obj的参数安装顺序传递进去。

我们先来看一下下面这段代码会输出什么:

function say(arg1, arg2) {
  console.log(this.name, arg1, arg2);
}

const obj = {
  name: "tom",
  say: function () {
    console.log(this.name);
  }
};
say();

输出结果:
在这里插入图片描述
我们发现报错了,程序并没有找到name
现在我们来改动一下,使用call函数来改变this的指向,看看会发生什么:

say.call(obj, "1", "2");

发现输出的结果变成了:
在这里插入图片描述
call把say函数的this变为了obj。

实现

下面我们来实现一个call函数

Function.prototype._call = function (context) {
  // 判断是否是一个函数
  // this指的是调用的函数
  if (typeof this !== "function") {
        throw new TypeError("Error");
  }
  context = context || window;
  context.fn = this;

  const args = [...arguments].slice(1);
  const result = context.fn(...args);

  delete context.fn;
  return result;
};

验证一下:

say._call(obj, "1", "2");

发现输出结果与期望的相同。

apply函数

语法

obj.apply(thisObj[,argArray]);

简介

applycall函数的用法相同,只是参数的传递变成了数组形式。

say.apply(obj, ["1", "2"]);

输出的结果与调用call相同:
在这里插入图片描述

实现

Function.prototype._apply = function (context, args) {

  // 判断是否是一个函数

  // this指的是调用的函数

  if (typeof this !== "function") {

    throw new TypeError("Error");

  }

  context = context || window;

  context.fn = this;

  let result = null;

  if (args) {

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

  } else {

    result = context.fn();

  }

  delete context.fn;

  return result;

};

bind 函数

语法

obj.bind(thisObj,arg[,arg2[,arg3[,...agr]]]);

简介

bind函数会返回一个新函数,但是不会像call和apply一样立即执行函数,bind后面的参数会当成obj的参数安装顺序传递进去。

我们先来看两段代码

const s = say.bind(obj, "1", "2");

s();
const s = say.bind(obj);

s("1", "2");

发现这两段代码输出的结果是一样的。

实现

我们利用apply来实现一下bind函数:

Function.prototype._bind = function (context) {

  // 判断是否是一个函数

  if (typeof this !== "function") {

    throw new TypeError("Error");

  }

  const args = [...arguments].slice(1);

  const fn = this;

  const F = function () {},

    fBound = function () {

      return fn.apply(

        this instanceof F && context ? this : context || window,

        args.concat(...arguments)

      );

    };

  F.prototype = this.prototype;

  fBound.prototype = new F();

  return fBound;

};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小白之旅

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值