search

Home  >  Q&A  >  body text

javascript - 在原生js中关于bind实现的一些疑惑

这里是原生js中bind的实现,我一些地方不是很理解,

if(!Function.prototype.bind){
    Function.prototype.bind=function(obj){
        var slice=[].slice,
        args=slice.call.(arguments,1),
        self=this,
        nop=function(){},
        bound=function(){
        return self.apply(this, instanceof nop ? this:{obj||{}}),
            args.concat(slice.call(arguments)))
        };
        nop.prototype=self.prototype;
        bound.prototype=new nop();
        return bound;

    };
}

关于它的上下文是怎么变化的,我能够理解
但是我不太清楚,第一:

nop.prototype=self.prototype;
        bound.prototype=new nop();

这里是在做什么?
第二是,这里的参数,关于参数数组的做法。

怪我咯怪我咯2902 days ago288

reply all(1)I'll reply

  • 巴扎黑

    巴扎黑2017-04-10 15:10:34

    首先你这个 Polyfill 应该自己加了料进去了,那个 this, instance of nop 应该是多了一个,,具体可参考 MDN 的 Polyfill 写法:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Glob...

    先回答一下问题二:明白 bind 的用法就必须要知道 apply 的用法,MDN 指出,apply 是直接修改了函数内部的指向到第一个参数,并将第二个参数数组传参进函数并运行这个函数。也就是说

    var obj = {test: function() { console.log(this, arguments) }},
        func = obj.test;
    
    obj.test("Hello", ",", "world", "!");
    func.apply(obj, ["Hello", ",", "world", "!"]);
    

    这两种运行方式是一样的。那么回到 Polyfill 中发现参数的写法是 args.concat(slice.call(arguments))args 是将 bind 时候定义的除第一个参数外的其它参数,而此时的 arguments 是指函数调用时候的参数,通过数组的操作将这两个参数合并成一个数组传入函数内部。看个例子你可能更容易明白:

    /** 代码接上 **/
    var newFunc = func.bind(obj, "Hello", ",");
    newFunc("world", "!");
    

    那么再来回答问题一,这个是典型的属性继承的方法,本来使用

    bound.prototype = self.prototype
    

    就可以将原属性集成过来了,但是这样两个对象属性都指向同一个地方,修改 bound.prototype 将会造成 self.prototype 也发生改变,这样并不是我们的本意。所以通过一个空函数 nop 做中转,能有效的防止这种情况的发生。

    reply
    0
  • Cancelreply