自学内容网 自学内容网

js 手写实现bind方法

在实现bind方法之前,我们知道call、apply和bind是三个重要的函数方法,它们都与函数调用和this关键字有关。本文将讲解它们之间的使用和区别以及bind的实现思路。

一、call、apply、bind

1.1 call方法

call方法是Function对象原型上的一个方法,它允许你在调用函数的同时显式指定函数的this值,并且可以传递多个参数。

function fn(val) {
  console.log(this, val);
}

const person = { name: "John" };

fn.call(person, "Alice");

在这里插入图片描述
从上面我们可以看出,this的指向发生了改变,指向了person。

1.2 apply方法

apply方法与call类似,但是它接收的参数是一个数组。

function fn(val) {
  console.log(this, val);
}

const person = { name: "John" };

fn.apply(person, ["Alice"]);

1.3 bind方法

bind方法创建一个新的函数,并将指定的对象绑定为新函数的this值。与call和apply不同的是,bind并不会立即调用函数,而是返回一个新的函数,新的函数可以再传值

function fn(...res) {
  console.log(this, res);
}

const person = { name: "John" };

fn.bind(person, "Alice")("Bob");

在这里插入图片描述

1.4 call、apply、bind区别

  • 使用call和apply时,函数会立即执行,而bind返回一个新函数不会立即执行。
  • call和apply的主要区别在于参数的传递方式,call是逐个传递,而apply是通过数组传递。

二、手写bind

2.1 普通函数调用情况

//原函数无返回值情况
function fn(...res) {
  console.log(this, res);   //this:person res:['Alice','Bob']
}
const person = { name: "John" };
console.log(fn.bind(person, "Alice")("Bob"));   //undefined


//原函数有返回值情况
function fn(...res) {
  console.log(this, res); //this:person res:['Alice','Bob']
  return "Hello WOrld";
}
const person = { name: "John" };
console.log(fn.bind(person, "Alice")("Bob")); //Hello WOrld

从上面我们可以看出,若原函数有返回值,则会成为新函数的返回值,否则为undefined

2.2 构造函数调用情况

function fn(...res) {
  console.log(this, res);   //this:fn   res: ['Alice', 'Bob2']
  return "Hello World";
}

const person = { name: "John" };

const f = fn.bind(person, "Alice");
console.log(new f("Bob2"));   //fn

从上面我们可以看出,使用 new 调用时,this 指向实例对象,返回值也是该实例对象。

2.3 bind手写实现

基于上面的探讨,我们明白bind除了考虑函数的返回值,还得考虑是普通函数调用还是构造函数调用。具体实现代码如下:

Function.prototype.myBind = function (thisArg, ...outerRes) {
  if (typeof this !== "function") {
    throw new Error("bind只能绑定函数");
  }
  const originFn = this;
  const innerFn = function (...innerRes) {
    if (this instanceof innerFn) {
      const targe = {};
      targe.__proto__ = originFn.prototype;
      originFn.apply(targe, outerRes.concat(innerRes));
      return targe;
    } else {
      return originFn.apply(thisArg, outerRes.concat(innerRes));
    }
  };
  return innerFn;
};

function fn(...res) {
  console.log(this, res);    //this:fn   res:['Alice', 'Bob2']
}
const person = { name: "John" };
const f = fn.myBind(person, "Alice");
console.log(new f("Bob2"));    //fn

我们面试中常常会遇到手写bind方法这个面试题,上面的代码就可以很好的应对。不过在实际开发中,往往需要考虑更复杂的情况,建议使用现有的bind方法,或者在需要的情况下使用现代的 JavaScript 特性,如箭头函数,以减少手动实现的复杂性。


原文地址:https://blog.csdn.net/weixin_45532665/article/details/136231928

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!