mozilla 的绑定函数问题

IT技术 javascript
2021-03-05 08:14:01

有一个关于我在 Mozilla 网站上找到的绑定函数实现的问题。在大多数情况下,这对我来说很有意义,但我无法弄清楚这张支票的用途......

this instanceof nop ? this : ( obj || {} ) 

在绑定函数中。显然它检查“this”是否是空函数,但为什么需要绑定空函数。我已经在萤火虫中试过了,它有效,但有什么意义呢?只是想增加我的 javascript 知识,所以任何帮助将不胜感激。

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;
  };
}
3个回答

它允许您将绑定函数作为构造函数调用,而无需绑定到原始对象。换句话说,如果您使用new.

下面是一个例子:

var obj = {};

function foo(x) {
    this.answer = x;
}
var bar = foo.bind(obj);   // "always" use obj for "this"

bar(42);
console.log(obj.answer);   // 42

var other = new bar(1);    // Call bar as a constructor
console.log(obj.answer);   // Still 42
console.log(other.answer); // 1

怎么运行的

为了简化解释,这里是代码的简化版本,它只绑定this而不处理参数或丢失的 obj 参数:

Function.prototype.bind = function( obj ) {
  var self = this,
  nop = function () {},
  bound = function () {
    return self.apply( this instanceof nop ? this : obj, arguments );
  };

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

  return bound;
};

这被返回的功能Function.prototype.bind不同,这取决于你是否使用它作为一个功能或构造方法的行为(参见第15.3.4.5.115.3.4.5.2中的ECMAScript 5语言规范)。主要区别在于它在作为构造函数调用时忽略“绑定 this”参数(因为在构造函数内部,this需要是新创建的对象)。因此该bound函数需要一种方法来确定它是如何被调用的。例如,bound(123)vs.new bound(123)并相应地设置this

这就是nop函数的用武之地。它本质上充当一个中间“类”,因此boundextends nopwhich extends self(即函数bind()被调用)。这部分设置在这里:

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

当你调用绑定函数时,它返回这个表达式:

self.apply( this instanceof nop ? this : obj, arguments ) )

this instanceof nop通过遵循原型链来确定 的任何原型this是否等于nop.prototype通过设置nop.prototype = self.prototypeand bound.prototype = new nop(),创建的任何对象new bound()都将使用来自selfvia的原始原型创建bound.prototype因此,函数调用里面,this instanceof nop(即Object.getPrototypeOf(NOP)== nop.prototype)是trueself被调用this(新创建的对象)。

在正常的函数调用中,'bound()'(没有newthis instanceof nop将是假的,因此obj作为this上下文传递,这就是您对绑定函数的期望。

使用中间函数的原因是为了避免调用原始函数(在 行中bound.prototype = new nop();),这可能会产生副作用。

@SunnyRGupta 我想我回答它的作用,但没有解释它的实际工作原理。它非常深入地了解 javascript 的工作原理,但我会看看我是否可以解释它。
2021-04-20 08:14:01
不知何故,我不明白nop上述内容如何影响这个答案。
2021-04-23 08:14:01
@TinaChen 该bind函数无法调用,new self()因为它调用了该函数,这可能会产生副作用。例如,如果您有这个函数:function f() { alert('oops'); }f.bind({})显示警报会令人惊讶(并且不正确)nop函数在 内部定义bind,并且不执行任何操作,因此调用是安全的。
2021-05-02 08:14:01
@SunnyRGupta 我不记得在编辑答案时 SO 是否会通知您,但我添加了一些关于 nop() 函数如何工作的解释。希望它至少有点意义。
2021-05-10 08:14:01
非常有趣,看起来正确 - 我从来没有想过 - 谢谢
2021-05-17 08:14:01

也许我完全错了,但是:

为什么不只使用调用 bind 的第一个函数的原型作为条件,而不是创建一个像 nop() 这样的新函数?,它对我有用。

也许出于某种原因创建 nop() 函数很重要,我还没有理解。(我是 JavaScript 新手)

Function.prototype.bind = function( obj ) {

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

bound.prototype = self.prototype;

return bound;
};

我认为这是一个简短的符号 (typeof obj != "undefined") ? obj : {}

也就是说,如果obj不是未定义,则返回obj,否则返回一个空对象({} 是一个空对象)。

嗯 - 不确定我是否只是不完全理解你的答案,因为我当然不是一个 javascript 专家,但让我停顿的部分是“这个 nop 实例?这个”似乎是说“这个”是空函数然后返回“this”——这意味着我们正在绑定空函数
2021-04-23 08:14:01
( obj || {} ) 部分非常清楚。令人困惑的是“nop”部分。
2021-04-25 08:14:01
对不起,你是对的,我快速阅读了,我错过了重点,让我再读一遍:)
2021-04-28 08:14:01