bind 的深刻浅出

目标:手写bind

官方定义:

  • 描述: bind()方法建立一个新的函数,在调用时设置this关键字为提供的值。并在调用新函数时,将给定参数列表做为原函数的参数序列的前若干项。
  • 返回值 : 返回一个原函数的拷贝,并拥有指定的this值和初始参数。

大白话讲 第一个参数 就是给this 这个东西 赋值,剩下的参数的意思是 用于bind 生成的新函数的参数,新函数的参数就等于 bind传入的除了第一个参数的剩下参数,而后再加上新函数本身传入的参数。浏览器

bind特性

  1. bind是函数的方法
  2. bind的第一个参数是this,剩下的参数做为新函数的前若干项的参数
  3. bind方法返回的是个函数,须要再次调用才会执行
  4. new的优先级比bind 高 this 不能被改变

手摸手实现bind

if (!Function.prototype.bind) { //若是浏览器不兼容 咱们就本身搞一个呗

    Function.prototype.bind = function(oThis){ // oThis 就是传入的第一个参数 目标 让它变成this的指向
        if(typeof this != 'function'){
            throw new TypeError("这东西是函数的方法,别的就别用了哈~")
        }
        
        var aArgs = Array.prototype.slice.call(arguments,1), // 第一个参数不是指this嘛,咱们把剩下的参数浅拷贝一份
            fToBind = this, // 这就是咱们的 this , 咱们要把这个this 改一改
            fBound = function() {  // 这东西 就是咱们最后返出去的 新函数 咱们要把它的 1. this改一改 2. 参数改一改
                //this instanceof fBound === true时,说明返回的fBound被当作new的构造函数调用
                //== false的时候说明当作了普通函数来调用,this为bind的第一个参数
                return fToBind.apply(this instanceof fBound?this:oThis,aArgs.concat(Array.prototype.slice.call(arguments)));
            }
        //原型链 再指向 原来this的原型链
        fBound.prototype = this.prototype;
        //返回咱们整的这个新函数
        return fBound;
    }
}

复制代码

这样看起来 貌似是搞定了,this也改变了,参数也搞定了,原型链也搞定了,是否是整完了???实际上 还有个坑app

function fn() {};
var bFn = fn.bind(null);
fn.prototype.value = 1;
console.log(bFn.prototype.value) //1
复制代码

这是什么鬼,这怎么 产生新函数 还把原函数给改了 原型链 传递的明显有问题啊 对象按引用传递 这样 咱们用一个中专的函数来处理这个问题函数

if(!Function.prototype.bind){
    Function.prototype.bind = function(){
        if(typeof this != "function"){
            throw new TypeError("这里报错提示")
        }
        var aArgs = Array.prototype.slice.call(arguments,1),
            fToBind = this,
            fNOP = function() {},
            fBound = function() {
                return fToBind.apply(this instanceof fBound?this:oThis,aArgs.concat(Array.prototype.slice(arguments)));
            }
        if(this.prototype){
            fNOP.prototype = this.prototype;
        }
        // 下行的代码使fBound.prototype是fNOP的实例,所以
        // 返回的fBound若做为new的构造函数,new生成的新对象做为this传入fBound,新对象的__proto__就是fNOP的实例
        fBound.prototype = new fNOP();
        
        //搞定!~
        return fBound;
    }
}
复制代码
相关文章
相关标签/搜索