【问题标题】:in javascript, "this" seems to get lost when function in within an object's object在 javascript 中,当函数在对象的对象中时,“this”似乎会丢失
【发布时间】:2011-08-01 06:37:22
【问题描述】:

对象 F 有一个存储为 this.fnthis.state.fn 的函数。 f.fn() 可以调用成功,但f.state.fn() 不能调用

函数 F( i, f ) { 这个.i = i; this.state = {'fn':f }; 这.f = f; }; F.prototype.inc = function() { this.i++ }; F.prototype.fn = function() { this.state.fn() }; f1 = new F(1, function() { console.log( this.i ); } ); f1.f(); // 这行得通 f1.inc(); // 这行得通 f1.state.fn; //打印函数 f1.fn(); // 不明确的! f1.state.fn(); // 不明确的!

问题似乎是函数存储在对象state中,因为这样可行:

f1.state.fn.call(f1); F.prototype.fn = function() { this.state.fn.call(this); };

这似乎暗示F.state.fn 中的this 上下文不是 F 而是F.state - 这对我来说完全违反直觉 - 这是对的吗!?

【问题讨论】:

    标签: javascript object scope this


    【解决方案1】:

    在函数中,this 完全取决于您调用函数的方式。

    当您使用点符号从对象中调用函数时,this 将自动设置为该对象。

    如果你说someObject.someChildObject.someFunction(),那么在someFunction() 内你会发现this 将被设置为someChildObject

    因此,在您的示例中,f1.fn() 应该导致 thisfn() 内成为 f1,但是在该函数中您说 this.state.fn() - 这将调用 statefn() 和 @987654334 @设置为state

    您可以使用callapply 覆盖此行为。

    另外一个你感兴趣的例子:

    function F( i, f ) {
            this.i = i;     
            this.state = { 'fn':f };
            this.f = f;
    };                      
    f1 = new F( 1, function() { console.log( this.i ); } );
    f1.f();   // works - 'this' will be f1
    var x = f1.f; // create a reference to the same function
    x();      // won't work - 'this' will probably be 'window'
    

    如果您创建对最初定义为对象属性的函数的引用并通过该引用调用该函数,那么this 将适用于您的新引用。在我的示例中,x 引用是全局的,这实际上意味着它属于 window 对象。从中可以了解到f1.f()调用的函数根本不属于f1

    继续这个例子:

    f2 = {};
    f2.i = "hello";
    f2.f = f1.f;
    f2.f(); // 'this' will be f2, so should log "hello"
    

    当您调用f2.f() 时,您会发现this 被设置为f2,并且因为我设置了一个属性f2.i,该函数将记录该属性。

    【讨论】:

    • 优秀!非常感谢您的启发和您在回答中所做的工作。
    【解决方案2】:

    Live example

    function F(i, f) {
        this.i = i;
        this.state = {
            'fn': f,
            i: 42
        };
        this.f = f;
    };
    F.prototype.inc = function() {
        this.i++
    };
    F.prototype.fn = function() {
        this.state.fn()
    };
    f1 = new F(1, function() {
        console.log(this.i);
    });
    f1.f(); // this works
    f1.inc(); // this works
    f1.state.fn; // prints the function
    f1.fn(); // 42!
    f1.state.fn(); // 42!
    

    当您调用state.fn() 时,它会打印this.i,在我的情况下是state.i,在我的情况下是42,在您的情况下是undefined

    您也可以强制this 不是state,而是通过这样做成为您期望的对象

    this.state = {
        'fn': f.bind(this)
    };
    

    .bind 是 ES5 但是你应该得到 ES5-shim

    【讨论】:

    • 绝对 - 很好的测试!但它仍然回到thisF 无关的事实,而是F.state - 这(实际上)让我大吃一惊!
    • 第一次阅读时错过了bind - 非常酷。似乎在 chrome 和 ff 上运行良好。
    • @cc_young bind 在旧版浏览器上失败。主要是FF3.6和IE8。 MDN 有一个垫片
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-09-01
    • 2019-04-19
    • 2023-03-03
    • 1970-01-01
    • 1970-01-01
    • 2017-07-23
    • 2015-02-17
    相关资源
    最近更新 更多