简体   繁体   English

将此绑定到嵌套文字对象中

[英]Bind this in nested literal object

Let's say I have this code 假设我有这段代码

(function() {

    function Foo(arg) {
        this.name = arg;
    }

    Foo.prototype = {
        bar: {
            baz: function() {
                alert(this.name); // Undefined...
            }
        }
    }

    var foo = function(arg) {
        return new Foo(arg);
    };


    window.foo = foo;

    return foo;
}());

foo("Anything").bar.baz();

How can I make "this" in my function "baz" refers to the object Foo without using bind or apply when I call it from outside ? 当我从外部调用对象时,如何在我的函数“ baz”中使“ this”指向对象Foo而不使用绑定或应用?

FWIW, I would strongly recommend not building nested structures like that, or at least not on the prototype, because the bar object is shared amongst all of the instances, which opens the door to a lot of cross-talk-style bugs. FWIW,我强烈建议不要建立这样的嵌套结构,或者至少不要在原型上建立嵌套结构,因为bar对象在所有实例之间都是共享的,这打开了许多串扰式bug的大门。 Instead, I'd create bar within the constructor. 相反,我会在构造函数中创建bar

How can I make "this" in my function "baz" refers to the object Foo without using bind or apply when I call it from outside ? 当我从外部调用对象时,如何在我的函数“ baz”中使“ this”指向对象Foo而不使用绑定或应用?

You may have bind and apply / call slightly confused. 您可能对bindapply / call感到有些困惑。 You wouldn't use bind when calling the function, but when creating it. 调用函数时,您将不会使用bind ,而在创建函数时,您将不使用bind Unless you use bind (or something equivalent to it), you can't do what you've said you want, because absent bind (or similar), this is set by how the function is called, and so this.bar.baz() will make this be this.bar within the call. 除非您使用bind (或等效的东西),否则您bind无法执行您想要说的话,因为缺少bind (或类似的东西), this this.bar.baz()函数的调用方式,因此this.bar.baz()this设为通话中的this.bar

Here's how you'd build bar within the constructor, and use bind to make baz use the correct this : 这是在构造函数中构建bar的方法,并使用bind使baz使用正确的this

function Foo(arg) {
    this.name = arg;
    this.bar = {
        baz: function() {
            alert(this.name);
        }.bind(this)            // <== Note
    };
}

Example: 例:

 function Foo(arg) { this.name = arg; this.bar = { baz: function() { snippet.log(this.name); }.bind(this) // <== Note }; } var f1 = new Foo("f1"); var f2 = new Foo("f2"); f1.bar.baz(); // "f1" f2.bar.baz(); // "f2" 
 <!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 --> <script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script> 


More about cross-talk: The naive thing to do is to just add one line to your Foo constructor, and keep bar on the prototype: 更多关于串扰:天真的事情做的是只有一个行添加到您Foo构造,并保持bar的原型:

this.bar.baz = this.bar.baz.bind(this);

That would be a very bad idea , because you'd get cross-talk between instances: 那将是一个非常糟糕的主意 ,因为您将在实例之间发生串扰:

 function Foo(arg) { this.name = arg; this.bar.baz = this.bar.baz.bind(this); // DON'T DO THIS } Foo.prototype = { bar: { baz: function() { snippet.log(this.name); } } }; var f1 = new Foo("f1"); var f2 = new Foo("f2"); f2.bar.baz(); // "f1" -- cross talk! Should be f2 
 <!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 --> <script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script> 

在声明时使用bind来适当地限制它的范围,例如

function foo() {}.bind(this);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM