手写实现call apply bind

2021-12-22  本文已影响0人  贵贵贵子

call apply bind 区别

这三个都是Function中自带的三个方法,都是可以改变this指向的,在Function.prototype上 可以打印看一下

console.dir(Function.prototype); //你会看的这三个属性以及arguments,toString等属性

call,apply的特点

call apply bind 用法

 let name = "张三";
    let Person = {
      name: "法外狂徒",
      age: 18,
    };
    function say(lag) {
      console.log(this);
      console.log(`my name is ${this.name},my age is ${this.age},我说${lag}`);
    }
    say("I love you"); //此时会打印Window    my name is 张三,my age is undefined,我说I love you;此时this指的是window可以获取到全局变量name
    //call
    say.call(Person , "I love you"); //my name is 法外狂徒,my age is 18,我说I love you, 此时函数中this就指向了Person
    //apply
    say.apply(Person, ["I love you"]); //my name is 法外狂徒,my age is 18,我说I love you  和call除了参数传数组外没什么不同
    //bind
    say.bind(Person, "I love you")(); //my name is 法外狂徒,my age is 18,我说I love you;bind返回的是一个函数,需要执行

实现call

在Function原型上加上自己的方法myCall;具体细节在注释

Function.prototype.myCall = function (ctx, args) {
      ctx = ctx ? Object(ctx) : window;
      args = args || [];
      const key = Symbol(); //创建一个独一无二的key以免覆盖原有属性
      ctx[key] = this; //将this赋值到传入对象ctx的某一个属性上;this指的是函数,结合上下文这里this就是say函数
      const result = ctx[key](...args); //将入参解构传入;并用result接收返回值
      delete ctx[key]; //用完后将此属性删除;不然每次call这个对象都会加个属性
      return result; //返回函数返回值
    };
    //执行myCall
    say.myCall(Person, ["I love you"]); //my name is 法外狂徒,my age is 18,我说I love you

实现apply

apply和call只是传参区别,稍微修改下即可;直接复制过来

Function.prototype.myApply = function (ctx, ...args) {
      ctx = ctx ? Object(ctx) : window;
      args = args || [];
      const key = Symbol(); //创建一个独一无二的key以免覆盖原有属性
      ctx[key] = this; //将this赋值到传入对象ctx的某一个属性上;this指的是函数,结合上下文这里this就是say函数
      const result = ctx[key](...args); //将入参解构传入;并用result接收返回值
      delete ctx[key]; //用完后将此属性删除;不然没吃call这个对象都会加个属性
      return result; //返回函数返回值
    };
 //执行myApply
    say.myApply(Person, "I love you"); //my name is 法外狂徒,my age is 18,我说I love you

实现bind

bind 是返回一个函数

Function.prototype.myBind = function (ctx, ...args) {
      ctx = ctx ? Object(ctx) : window;
      args = args || [];
      const _this =this
      return function (...rest) {
        const key = Symbol(); //创建一个独一无二的key以免覆盖原有属性
        console.log(this)//这里的this指向window,因为返回的是一个函数,this永远指向最后调用它的那个对象,最终调用这个函数的是window
        ctx[key] = _this; //将this赋值到传入对象ctx的某一个属性上;this指的是函数,结合上下文这里this就是say函数
        const result = ctx[key](...args,...rest); //将入参解构传入;并用result接收返回值
        delete ctx[key]; //用完后将此属性删除;不然没吃call这个对象都会加个属性
        return result; //返回函数返回值
      };
    };
    //执行myBind
    say.myBind(Person, "I love you 1")(); //my name is 法外狂徒,my age is 18,我说I love you
上一篇下一篇

猜你喜欢

热点阅读