简体   繁体   中英

Execution context of sequential function calls - this changes to window

I'm sorry to ask such a basic question but despite lots of reading on javascript over the last few months and on this issue specifically, I'm just not getting something about it's execution context and "this". So I'm hoping an explanation using my specific scenario will help. I have a constructor in which I have some local functions and some exposed functions (mimicking public/private methods).

function blog() {
    if (!(this instanceof blog))
        return new blog();

    function internal(){
        alert(this);
    }

    this.external = function(){
        alert(this);
        internal();
    }
}

var b = new blog();
b.external();

In external , "this" is b, an instance of blog as I expect. I was wrongfully expecting this to hold true inside internal as well, but it's actually the global window object. As an experiment I tried changing external 's call to this.internal() which gives an error that this.internal is not a function. This is when I realized I'm really not following how it's working. Ok, I haven't defined a property of blog named internal, but if internal isn't a function defined on my blog instance, what is it and where is it defined? Maybe I have this structured wrong.

Please see xdazzs answer here: https://stackoverflow.com/a/12241726/2469255

However, to solve your problem you need to define what this is to that function.

Your internal call is called without providing a this context so it binds to the global object, unlike you this.external which has scoped it to the blog object. rewriting your code as follows will solve this:

function blog() {
    if (!(this instanceof blog))
        return new blog();

    function internal(){
        console.log(this);
    }

    this.external = function(){
       console.log(this);
       internal.bind(this);
       internal.call(this); // this in internal will be the object blog.
    }
}

var b = new blog();
b.external(); //blog {external: function} blog {external: function}

Alternatively a lot of people prefer the var self = this to ensure problems like this don't occur and you know exactly what's being set, where. There's a lot of contention over that particular thought so YMMV

Let me try to explain.

This piece of code bellow will only be reachable, if you simple call blog() without a new key word.

if (!(this instanceof blog))
    return new blog();

But, this is not a recommended pratice, cause it's affecting the clearly of your code.

Because this:

var realObj = new Blog();

is the right code to instantiate an Object and the code bellow:

var obj = blog();

are not clear enough and could guide you to mistakes.

JavaScript have originally a Prototypal Inheritance and you have a better explaination here from Douglas Crockford.

The main reason that internal() don't have the same reference from external is because internal have a scope pointing to global and when you create an instance of blog the external scope are pointing to object blog.

Really confuse because this inside the declaration of blog are pointing to global, so why when you instantiate blog this change?

When browser start to read your code, it put what it found in memory, referencing by the scope. Remember scope are controlled with {} , so when he found your declaration this.external he associate to the scope and when you declare using new this become the scope of the object so this don't refer anymore to global scope.

take a look at this code at jsbin.com

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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