自己实现call,apply,bind

自己尝试一下如何实现call,apply,bind

  • 第一步我们先在Function的原型上面新建一个函数吧.叫myApply
const obj = {
    name:'joy',
};

function getName() {
    console.log(this.name);
}

Function.prototype.newApply= function () {
    console.log(this);
};

getName.newApply(); //ƒ getName(){ console.log(this.name); }

这时候打印出来,this是getName这个函数.
根据我之前写过的一篇文章 (确定this的指向)
得知,this绑定的优先级是

箭头函数 > new > 显式 > 隐式 > 默认绑定

call,apply是属于显示绑定,那肯定不能用箭头函数和new来代替了,否则优先级就改变了,那就只能用隐式绑定的方式了

  • 所以我们要用隐式绑定的方式去改变this的指向
const obj = {
    name:'joy'
};

function getName(){
    console.log(this.name);
}

Function.prototype.newApply= function (that) {
    that.myFn = this;
    const result = that.myFn();
    return result
};

getName.newApply(obj); //joy

这里已经是初步完成了改变this指向的功能了,让我们在来完善一下

  • 加上传递参数和不传this调用
const obj = {
    name:'joy'
};

function getName(a,b){
    console.log(this.name,a,b);
}

Function.prototype.newApply = function (that,arg) {
    if(typeof this !== 'function'){
        throw this+'is not a function'
    }
    that = that || window; //因为第一个参数如果不传就会绑定到window上面
    arg = arg || [];
    that.myFn = this;
    const result = that.myFn(...arg); //解构赋值把参数传进来,先把结果存起来
    delete that.myFn; //再删除,否则就有副作用了
    return result;
};

getName.newApply(obj,[1,2]); // joy
  • 这样一个apply就完成了,可能还有些地方没考虑到,但是大概功能都出来了,call也是差不多就是传参不太一样
const obj = {
    name:'joy'
};

function getName(a,b){
    console.log(this.name,a,b);
}

  Function.prototype.newCall = function (that, ...arg) {
            if (typeof this !== 'function') {
                throw this + 'is not a function'
            }
            that = that || window; //因为第一个参数如果不传就会绑定到window上面
            that.myFn = this;
            const result = that.myFn(...arg); //解构赋值把参数传进来,先把结果存起来
            delete that.myFn; //再删除,否则就有副作用了
            return result;
        };

        getName.newApply(obj, 1, 2); // joy 1 2

以上就是apply和call自己实现的方式了.

  • 接下来到一个难点bind了,bind有点不一样,call和apply是绑定直接调用,而bind是绑定不调用,返回绑定后的函数
  • 那么直接利用apply不就可以了
    const obj = {
        name:'joy'
    };

    function getName(){
        console.log(this.name);
    }

    Function.prototype.newBind = function (that) {
        const fn = this;
        return function () {
            fn.apply(that)
        }
    };

    getName.newBind(obj)() //joy
  • 再优化一下
    const obj = {
        name:'joy'
    };

    function getName(){
        console.log(this.name);
    }

    Function.prototype.newBind = function (that) {
        if (typeof this !== 'function') {
            throw new TypeError('Error')
        }
        const args = [...arguments].slice(1);
        const fn = this;
        return function () {
            fn.apply(that)
        };
        // 返回一个函数
        return function F() {
            // 因为返回了一个函数,如果是new的话this就要指向新创建的对象了
            if (this instanceof F) {
                return new fn(...args, ...arguments)
            }
            return fn.apply(that, args.concat(...arguments))
        }
    };

    getName.newBind(obj)() //joy

以上就是实现call,apply,bind的内容了

你可能感兴趣的:(自己实现call,apply,bind)