“var” variables, “this” variables and “global” var

2019-02-14 00:41发布

问题:

After my last question, this one is more accurate for me:

example:

function Foo() {
    this.bla = 1;
    var blabla = 10;
    blablabla = 100;
    this.getblabla = function () { 
        return blabla; // exposes blabla outside
    }
}
foo = new Foo();

what I understand now:

this.bla = 1;     // will become an attribute of every instance of FOO.
var blabla = 10;  // will become a local variable of Foo(will **not** become an attribute of every instance of FOO), which could be accessed by any instance of FOO - only if there's a method like "this.getBlabla". that's a "closer" ?
blablabla = 100;  // will define a **new** (or change if exist) global(window) variable.

Do I understand correctly?

Also - if I include var blabla = 10; and the getblabla function that uses it in the contractor, then for every instance of Foo("foo"...), there will be saved a Foo contractor function in the memory that includes this "private" variable. or will it be the same Foo function as place for the private variables - for ALL instances(like "foo") of Foo?

回答1:

Just to focus on the scope, I'm going to run through this example, (with clearer variables) Afterwards, I'll connect it back to your variables.

var x = "Global scope";
var y = "Not changed.";

function Foo() {
    this.x = "Attribute of foo";
    var x = "In foo's closure";
    y = "Changed!"
    this.getX = function () { 
        return x;
    }
}

// do some logging

console.log(x); // "Global scope"
console.log(y); // "Not changed"
foo = new Foo();
console.log(y); // "Changed!"
console.log(foo.x); // "Attribute of foo"
console.log(x); // "Global scope"
console.log(foo.getX()); // "In foo's closure"

The line: this.x is equivalent to this.bla, and it defines an externally available attribute of a Foo object. y is equivalent to blablabla=100 and then the x within foo is equivalent to your blablabla within foo. Here's a really rough jsfiddle you can run to see this.



回答2:

Everything you've said is correct. (Of course, an error will be thrown at the blablabla assignment in Strict Mode.

On the second half, there's nothing special about the constructor function. It just acts like any other function in that it creates a closure that persists as long as its referenced (the lifetime of this.getblabla in this case).

Take this example:

function initBlaBla() {
    var blabla = 10;
    this.getblabla = function () { 
        return blabla; // exposes blabla outside
    }
}

function Foo() {
    this.bla = 1;
    blablabla = 100;
    initBlaBla.call(this);
}

foo = new Foo();

Here, the Foo constructor doesn't form a closure and its scope gets released immediately. initBlaBla on the other hand creates a closure. Interestingly, the compiler may see that blabla is never written to and optimize this.getblabla to always return 10 and never save the closure scope. This can be seen when you break execution in a function inside a closure and try reading a value it doesn't internally reference.

The closure scope will get released and queued for garbage collection if you call any of the following:

delete foo.getblabla;
foo.getblabla = "Anything!";
foo = "Anything else.";


回答3:

Yes, you understand it!
As for the second part of the question, it is all about inheritance, just like the relation between (global) window and the functions defined in it's scope (think root). So everything you do not re-specify, will be looked up at the ancestor.

This is a tremendous good video by Crockford, who explains it REALLY well.