美文网首页手绘散文想法
js中的bind方法并模拟实现自己的bind方法

js中的bind方法并模拟实现自己的bind方法

作者: 绿芽 | 来源:发表于2022-07-22 10:34 被阅读0次

    Js中bind方法使用和实现

    前面我们已经模拟实现了call和apply方法,今天来实现下同样可以改变this指向但是又有点不同得方法--> bind方法。

    定义

    首先来看下bind方法在mdn中得定义,bind() 方法创建一个新的函数,在 bind() 被调用时,这个新函数的 this 被指定为 bind() 的第一个参数,而其余参数将作为新函数的参数,供调用时使用。

    语法

    function.bind(thisArg[, arg1[, arg2[, ...]]])

    参数

    thisArg 调用绑定函数时作为 this 参数传递给目标函数的值。 如果使用new运算符构造绑定函数,则忽略该值。当使用 bind 在 setTimeout 中创建一个函数(作为回调提供)时,作为 thisArg 传递的任何原始值都将转换为 object。如果 bind 函数的参数列表为空,或者thisArg是null或undefined,执行作用域的 this 将被视为新函数的 thisArg。
    arg1, arg2, ... 当目标函数被调用时,被预置入绑定函数的参数列表中的参数。

    返回值

    返回一个原函数的拷贝,并拥有指定的 this 值和初始参数。

    从上面mdn中得描述中我们看到bind方法和call、apply方法得不同点就是,bind方法同样是将调用函数得this指向第一个参数,但是这个时候不会执行函数,而是会创建一个新的函数并返回出来,除了第一个参数剩下得参数传入新返回得函数使用。并且返回的函数还可以被new操作符进行调用,使用new操作符时bind方法传入得第一个this指向得值就失效了,此时函数this得指向遵循new操作符的this指向原则。(new操作符解析)。

    使用

    function say(res, res2) {
            this.num = res;
            console.log(this);
            console.log(this.hello);
            console.log(res);
            console.log(res2);
        }
        let obj = {
            hello: 'hello'
        }
        const back = say.bind(obj, 1);
        back(3);
        // {hello: "hello", num: 1}
        // hello
        // 1
        // 3
    

    上述代码由打印值可以看出,利用bind函数将say函数内部的this指向了obj对象,并且为obj对象添加了一个属性num赋值为1,并且bind函数返回的back函数传入的参数在bing函数传入参数的后面进行传入。但是没有使用new操作符,接下来看使用new操作符调用back函数。

        function say(res, res2) {
            this.num = res;
            console.log(this);
            console.log(this.hello);
            console.log(res);
            console.log(res2);
        }
        let obj = {
            hello: 'hello'
        }
        const back = say.bind(obj, 1);
        const b = new back(6);
        console.log(b, 'b')
        // say {num: 1}
        // undefined
        // 1
        // 6
        // say {num: 1} "b"
    

    上述代码将bind函数返回的back函数使用new操作符调用,看打印结果将say函数的this指向了new操作符生成的实力对象b上。下面我们就根据规则实现模拟实现自己的bind操作符。

    实现思路

    1、 在Function的原型上添加自己的bind方法
    2、 返回一个新的函数backFn
    3、 判断函数是不是由new操作符调用
    4、 是的话将this指向生成的实力对象,不是的话将this指向传入的第一个值
    5、 如果原函数存在原型对象,将返回函数backFn的原型指向原来函数的原型对象(因为bind返回的函数相当于原函数的复制)
    6、 返回backFn函数

    实现

        // 添加bind方法,并传入参数
        Function.prototype.myBind = function (thisArg, ...bindRes) {
            // 将函数保存起来
            const thisFn = this;
            if (typeof thisFn !== 'function') {
                throw new TypeError(this + 'is not a function');
            }
            const backFn = function (...backRes) {
                // 判断是否是new操作符调用,是的话采用生成的实例对象(因此时backFn函数this就指向实例对象所以直接指向this即可)
                // 参数传入如果是es5实现可以使用arguments对象
    
                // 使用之前自己写好apply方法改变this指向
                if (new.target) {
                    return thisFn.apply(this, [...bindRes, ...backRes]);
                } else {
                    return thisFn.apply(thisArg, [...bindRes, ...backRes]);
                }
                // 或者也可以这样子写
                // return thisFn.apply(new.target? this: thisArg, [...bindRes, ...backRes]);
    
            }
            // 采用创建空函数的方法,将bacnFn函数原型指向原函数防止改变bacnFn函数原型对象而影响原函数原型对象
            if (thisFn.prototype) {
                const emptFn = function () {};
                emptFn.prototype = thisFn.prototype;
                backFn.prototype = new emptFn();
            }
    
            return backFn;
        }
    

    测试

        function say(res, res2) {
            this.num = res;
            console.log(this);
            console.log(this.hello);
            console.log(res);
            console.log(res2);
        }
        say.prototype.str = '内容'
        let obj = {
            hello: 'hello'
        }
        const back = say.myBind(obj, 1);
        back(3);
        // {hello: "hello", num: 1}
        // hello
        // 1
        // 3
    
    
    
        const b = new back(6);
        console.log(b.str, 'b')
        // backFn {num: 1}
        // undefined
        // 1
        // 6
        // 内容 b
    

    测试结果符合期望结果,至此我们自己的bind方法就实现了。

    相关文章

      网友评论

        本文标题:js中的bind方法并模拟实现自己的bind方法

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