Eugene Yu
Eugene Yu

Reputation: 3968

access outer variable that has changed after its first creation

I know I can access outer variable in function object but, here is what I'm stuck with.

zero = function (one) {
    this.one = one;
    this.two = {
        three: {
            four: function() {
                one.test();
            }
        }
    }
}

Sorry for the dirty code naming :(. But here's the test case.

foo = {
    test: function() {
        console.log('foo test');
    }
}
bar = new zero(foo);
bar.two.three.four(); // prints 'foo test'
foo2 = {
    test: function() {
        console.log('another foo test');
    }
};
bar.one = foo2;
bar.two.three.four(); // still prints 'foo test' instead of 'another foo test'

It looks like four keeps the reference of one since its creation not the reference of variable in bar. And I cannot figure out how I can directly access to the outer variable. Thanks for reading my question.

Upvotes: 0

Views: 30

Answers (1)

Qantas 94 Heavy
Qantas 94 Heavy

Reputation: 16020

Use

var zero = function (one) {
    var _this = this;
    this.one = one;
    this.two = {
        three: {
            four: function () {
                _this.one.test();
            }
        }
    };
};

instead of

one.test();

That uses the closure variable instead of the publicly visible instance property.

When you do this:

this.one = foo2;

What you're actually doing is overwriting the publicly visible property. However, this is distinct from the argument to your function called one, which is within the scope of your function created. one is never changed in your code, therefore it's only natural that you're getting the valve from the initial assignment in your constructor function. Assigning a property to an object does not mean that they will be the same. If you do this inside a constructor:

function Test()
{   var test = {};
    this.test = test;
    test = { a: 1 };
    console.log(this.test.a);
}

new Test; // undefined is logged

The reason why _this is used in the new function is that the value of this is only set when the function is called, not when it is defined. For example, take this behaviour:

function Example()
{   var _this = this;
    this.test1 = { func: function () { return this; }
    this.test2 = { func: function () { return _this; }
}

var instance = new Example;
var randomFunction1 = instance.test1.func;
var randomFunction2 = instance.test2.func;

instance.test1.func(); // the instance.test1 object
instance.test2.func(); // the actual instance

randomFunction1(); // the global object (though this will be undefined in strict mode)
randomFunction2(); // still the instance

The first is the way it is because the parent object of the method is instance.test1, not instance. By assigning the object reference at that time to a variable, we can permanently store this reference and refer to it any time that you like.

Note: you might want to use var to declare your variable - this prevents implied globals which can be particularly nasty, and also assignments to undeclared variables are not permitted in strict mode.

Upvotes: 2

Related Questions