开发者

Scope of self-invocation function in Javascript

Why does self-invocation function inside a function don't get the scope of the outer function in JavaScript?

var prop = "global";

var hash = {
    prop: "hash prop",
    foo: function(){
        console.log(this.prop);
        (function bar(){
            console.log(this.prop);
        })();
    }
};

var literal = {
    prop: "object"
};

hash.foo();
// hash prop
// global

hash.foo.call(literal);
// object
/开发者_JS百科/ global

Looks like altering the scope of the outer function has no effect on the scope of the inner self-invocation function.

PS: The question is not about how to alter the scope of the inner function. But what is the proper explanation in the "Javascript language" perspective? Does all self executing functions have 'global' scope by default? If so, why?


Your problem is the this and what it references:

foo: function(){
    console.log(this.prop);
    (function bar(){
        console.log(this.prop);  <--- this does not reference to foo here, but instead it refers to the window object
    })();
}

You need to keep a reference to the outer this:

foo: function(){
    console.log(this.prop);

    var that = this;
    (function bar(){
        console.log(that.prop);  <--- tada!
    })();
}

Update
Some explanation. It's all about how JavaScript determines the context when invoking a function.

function Test() {
    this.name = "Test";
    this.bar = function() { console.log("My name is: "+ this.name);}
}

function Blub() {
    this.name = "Blub";
    this.foo = function() { console.log("My name is: " + this.name);}
} 

var a = new Test();
var b = new Blub();

// this works as expected
a.bar(); // My name is: Test
b.foo(); // My name is: Blub

// let's do something fun
a.foo = b.foo; // make an educated guess what that does...

a.foo() // My name is: Test

Huh? Aren't we referencing the method of Blub? No we're not. We are referencing the unbound function of Blub.

JavaScript binds on . (dots) and based on that it decides waht the value of this should be.

Since you're not calling your anonymous function on an object (therefore no .) it will make this reference to the global object, which is - in case of the browser - the window object.

Another example (one might think this would work):

var str = "Hello World";
var ord = str.charCodeAt; // let's make a little shortcut here.... bad idea

ord(0) // no dot... 

Instead of the char codes that are in str we get the ones that are in the global object, of course that's not a string so charCodeAt calls toString on which results in "[object DOMWindow]"


You are not applying any object as the this context when you call the inner function, so it gets this set to window by default. If you wanted to call the closure with the same this as the outer function, you would have to do:

(function bar(){
    console.log(this.prop);
}).call(this);

Or:

var that = this;
(function bar(){
    console.log(that.prop);
})();
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜