2

Okay, I stumbled upon this piece of code..

How come this works? What sort of evil scheme does JavaScript use to resolve variables?

The way I see it, as a C++ kind of guy: the class/object definition contains a non-existent reference to an object of the class being defined. Seriously, how?

(To be honest, I understand partially - I could deduce a strawman concept of how and when JS resolves names.. but maybe this way the question will be of more use to someone else, someday)

Guilty code:

function Sio() {
    this.someValue = 5;
    this.doStuff = function() {
        console.log("look: "+howDoYouResolveThisYouFoulCreature.someValue);
    };
}

var howDoYouResolveThisYouFoulCreature = new Sio();

That seems so wrong.

3 Answers 3

3

Lots of concepts here, and I'm not sure which one is giving you troubles…

The two most likely ones are new / this and var.

new / this

When you call a function the value of this is determined by the context in which you call it.

If you use the new keyword, you create an instance of the function and make that instance the context.

When you call howDoYouResolveThisYouFoulCreature.doStuff() you are accessing that instance as a global. It would usually make more sense to:

this.doStuff = function() {
    console.log("look: "+ this.someValue);
};

Since foo.doStuff() makes foo the context for that invokation of doStuff() (which makes the function reusable between different instances of Sio)

var

  1. Scope in JavaScript is at the function level.
  2. Using var something anywhere inside a function will scope that variable to that function
  3. It is considered good practise to use a single var statement at the top of a function to avoid confusion

Also, the doStuff function is not called before howDoYouResolveThisYouFoulCreature has a value. Until that point all that matters is that the function is syntactically correct, it doesn't matter what type the variable is.

Sign up to request clarification or add additional context in comments.

Comments

1

It works because the function() this.doStuff isn't executed before howDoYouResolveThisYouFoulCreature is created. Keep in mind for as many new Sio()'s that you make this will always console.log the howDoYouResolveThisYouFoulCreature.someValue regardless of the variable name that doStuff() is called from.

Comments

1

This works because:

var howDoYouResolveThisYouFoulCreature = new Sio();

... actually resolves into:

var howDoYouResolveThisYouFoulCreature;
howDoYouResolveThisYouFoulCreature = new Sio();

So at the time the function doStuff is assigned, the var is already declared.

Edit: Forget that, I was being foolish. It turns out pimvdb is right, and here's the proof (also on jsfiddle):

function A() {
    this.logValue = function() {
        if (b === undefined) {
            console.log('Wah, wah, wah...');
        } else {
            console.log(b.someValue);
        }
    };
}

function B() {
    this.someValue = 42;
}

var a = new A();
a.logValue(); // Wah, wah, wah...

var b = new B();
a.logValue(); // 42

So the execution context is the key. When Sio (or, in this case, A) is constructed, it's scoped to where b might, at some point, be defined. The variable isn't resolved until the function is called, at which point it might be defined. Or not. No biggie. :-)

1 Comment

This does not necessarily matter; you can also assign a function to a variable if that function refers to a non-existent variable.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.