js 手写实现call,apply,bind方法及它们区别

首先我们先说一下这三个方法是干什么的?

  • call 和 apply 是为了改变某个函数运行时的上下文(context)。意思就是为了改变函数内部的this指向。
  • bind方法的主要作用是将函数绑定到一个对象上,并返回一个函数,作为指定对象的方法执行该函数,bind方法可传递参数。
    使用:
function a(arg){
  console.log(this.name,"我的参数是" + arg)
}
const obj = {
  name:"我是对象"
}
a.call(obj,"call");      // 我是对象 我的参数是call
a.apply(obj,["apply"]); // 我是对象 我的参数是apply
a.bind(obj,"")();      // 我是对象 我的参数是bind

那么他们有什么区别呢?

  • call方法的第一个参数是要绑定给this的值,默认是window。后边接受一个参数列表。
  • apply方法接受两个参数,第一个参数是要绑定给this的值,默认值也是window,第二个参数是一个参数数组。
  • bind方法 第一个参数要绑定给this的值,后边的参数是参数列表。区别在于bind方法返回值是函数。
  • call和apply方法会直接执行该函数,bind方法不会直接执行。

接下来我们手写实现三个方法

call方法的实现:

Function.prototype.call(newThis,...arg){
    const newThis.fn = this;// 这样写有一个问题 那就是可能覆盖原有属性fn
    return newThis.fn(...arg)
}

Function.prototype.call(newThis = window,...arg){
    // 我们还需要给newThis 一个默认值,如果没有传递this 默认就是window
    const fn = Symbol('fn'); // 我们声明一个独一无二的属性
    newThis[fn] = this
    return newThis[fn](...arg)
}

apply方法的实现:

apply方法的实现方法和call方法差不多,需要注意的就是参数传递的问题

Function.protptype.apply(newThis = window,arg){
    // 我们还需要给newThis 一个默认值,如果没有传递this 默认就是window
    const fn = Symbol('fn'); // 我们声明一个独一无二的属性
    newThis[fn] = this
    return newThis[fn](...arg)
}

bind方法的实现:

Function.prototype.bind(newThis,...arg){
  const that = this;
  const newFunction = function (){
    const self =  this instanceof that ? this : thisArg;// 保证this的指向
    that.apply(self,arg.concat(Array.prototype.slice.call(arguments)));
    // newBind函数还可以接受参数,所以需要把newBind函数的参数和原函数的参数合并在一起
  }
  // 还需要继承原型上的属性和方法
  Function.prototype = Object.create(that.prototype);

  return newFunction
}

你可能感兴趣的:(js 手写实现call,apply,bind方法及它们区别)