美文网首页让前端飞
自己实现call,apply,bind

自己实现call,apply,bind

作者: 土豪码农 | 来源:发表于2019-03-01 22:34 被阅读6次

    自己尝试一下如何实现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.newApply = function (that,arg) {
        if(typeof this !== 'function'){
            throw this+'is not a function'
        }
        that = that || window; //因为第一个参数如果不传就会绑定到window上面
        arg = [...arguments].slice(1); //先把arguments拿到,然后slice截取从1到最末尾
        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

        本文链接:https://www.haomeiwen.com/subject/xdzjuqtx.html