手写js系列之 bind 看不懂注解打死我

 Function.prototype.myBind = function (context, ...args) {
            if (!context || context === null) {
                context = window;
            }
            // 创造唯一的key值  作为我们构造的context内部方法名
            let fn = Symbol();
            context[fn] = this;
            let _this = this;
            //  bind情况要复杂一点

            const result = function (...innerArgs) {

                //进入里面后 这里的this和外面的this不一样了,现在是指向new result的this
                //this是通过result构造函数生成的一个实例对象,不是一个函数,所以可以this instanceof _this
                //而_this是Person这个构造函数对象
                // 第一种情况 :若是将 bind 绑定之后的函数当作构造函数,通过 new 操作符使用,则不绑定传入的 this,而是将 this 指向实例化出来的对象
                // 此时由于new操作符作用  this指向result实例对象  而result又继承自传入的_this 根据原型链知识可得出以下结论
                // this.__proto__ === result.prototype   //this instanceof result =>true
                // this.__proto__.__proto__ === result.prototype.__proto__ === _this.prototype; //this instanceof _this =>true
                if (this instanceof _this === true) {
                    // 此时this指向指向result的实例  这时候不需要改变this指向
                    this[fn] = _this; //result 得到person构造方法
                    //这里的...args还用到了闭包!!所以返回后还存在不会消失
                    //得到一个函数 等着输入innerages就可以和args结合去干事了
                    this[fn](...[...args, ...innerArgs]); //这里使用es6的方法让bind支持参数合并
                    delete this[fn];
                } else {
                    // 如果只是作为普通函数调用  那就很简单了
                    // 直接改变this指向为传入的context
                    //执行
                    context[fn](...[...args, ...innerArgs]);
                    delete context[fn];
                }
            };

            //上面的result返回了,但是100行存参不执行(闭包),这里下面的这句执行了,为
            //if (this instanceof _this === true)做了铺垫了
            // 如果绑定的是构造函数 那么需要继承构造函数原型属性和方法
            // 实现继承的方式: 使用Object.create
            result.prototype = Object.create(this.prototype);//this是person的
            //右边创了一个原型对象实例
            //实现继承 (其实就是new Person())
            //这样后,result构造函数指向的原型对象t,t的_proto_就是Person构造函数的原型对象
            //通过result new 出来的_proto_指向了t
            //所以instanceof里可以找到用result new出来的
            function instanceOf(left, right) {
            
                let proto = left.__proto__
                while (true) {
                    if (proto === null) return false
                    if (proto === right.prototype) {
                        return true
                    }
                    proto = proto.__proto__
                }
            }


            return result;
        };

        //用法如下

        function Person(name, age) {
            console.log(name); //'我是参数传进来的name'
            console.log(age); //'我是参数传进来的age'
            console.log(this); //构造函数this指向实例对象
        }
        // 构造函数原型的方法
        Person.prototype.say = function () {
            console.log(123);
        }
        let obj = {
            objName: '我是obj传进来的name',
            objAge: '我是obj传进来的age'
        }
        // 普通函数
        function normalFun(name, age) {
            console.log(name);   //'我是参数传进来的name'
            console.log(age);   //'我是参数传进来的age'
            console.log(this); //普通函数this指向绑定bind的第一个参数 也就是例子中的obj
            console.log(this.objName); //'我是obj传进来的name'
            console.log(this.objAge); //'我是obj传进来的age'
        }

        // 先测试作为构造函数调用
        // let bindFun = Person.myBind(obj, '我是参数传进来的name')
        //到上面这一步还不能确定是构造函数,到下面的result才会得到那些instanceof信息
        //只能得到一个函数展开就是那样的,没调用呢,把参数存进去而已,得到一个有参数的函数
        //对象

        //返回的是一个obj去调用的Person构造函数
        // let a = new bindFun('我是参数传进来的age')//function (...innerArgs)
        // a.say() //123

        // 再测试作为普通函数调用
        let bindFun = normalFun.myBind(obj, '我是参数传进来的name');
        //生成一个函数bindFun
        //  两个参数得去合并啊
        bindFun('我是参数传进来的age');
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值