Few days ago I met a very interesting JS interview question. It claims that this question covered almost all aspect that every JS programmer should understand. And here is the question:

For me, I only managed to answer 5 of them correctly. After that I did some research and figured the correct answers with corresponding explanation.

Spoiler Warning!

You should attempt them first before looking at my explanation

Let’s look at them one by one.

1
Foo.getName();

This should be quite straightforward.
It actually calls a property of the Foo object (which is an anonymous function, but function is also an object in JavaScript). And we have defined this getName property in

1
2
3
Foo.getName = function() {
alert(2);
};

Hence, the alert value will be 2 .

Next,

1
getName();

This one is rather confusing. Because if you check the declaration of getName, there are two of them there:

1
2
3
4
5
6
7
8
9
// "Anonymous" function Expression
var getName = function() {
alert(4);
};
// function declaration
function getName() {
alert(5);
}

Both of them will work for getName(), but which one to use? Naturally, we think since the later function declaration will overwrite the first “Anonymous” function expression, and hence the answer is 5 . However, this is not true.

You raise me up — Hoisting in JavaScript

There is a very interesting behaviour in JavaScript called “Hoisting”.
Consider following code

1
2
3
console.log( a );
var a = 2;

What do you expect to be printed in the console.log(..) statement? error? undefined? 2?
Many of us will think how can you use a variable before you declare it? So it seems that a ReferenceError will be thrown.
However, surprisingly, it will print undefined.
Well, it’s all about compiler .
When the compiler sees a variable declaration, such as var a = 2;, it does not think of that as one statement. It actually thinks of it as two statement: var a; and a = 2;. The first statement, the declaration, is processed during the compilation phase. The later statement, the assignment, is left in place for the execution phase. Declarations are raised to top by compiler, and this is what we called Hoisting .

So the example we saw just now, in compiler’s perspective, is like this:

1
2
3
4
5
var a;
console.log( a ); // undefined
a = 2;

And it’s quite clear that why undefined will be printed.

In addition, both function declarations and variable declarations are hoisted. Which one first? For the same name of “duplicate” declarations, functions are hoisted first, and then variables.
Consider:

1
2
3
4
5
6
7
8
9
10
11
foo(); // 1
var foo;
function foo() {
console.log( 1 );
}
foo = function() {
console.log( 2 );
};

1 will be printed instead of 2. Because the compiler will see it as:

1
2
3
4
5
6
7
8
9
function foo() {
console.log( 1 );
}
foo(); // 1
foo = function() {
console.log( 2 );
};

Notice that var foo was the duplicate (and thus ignored) declaration, even though it came before the function declaration, because function declarations are hoisted before normal variables.

So back to our question, a more precise view of the order are:

1
2
3
4
5
6
7
8
9
// function declaration first
function getName() {
alert(5);
}
// variable assignment
getName = function() {
alert(4);
};

And hence, when we called getName(), we will print 4 .

Next, let’s consider

1
Foo().getName();

What will be returned by Foo()?

1
2
3
4
5
6
function Foo() {
getName = function() {
alert(1);
};
return this;
}

It will return this, a keyword that confuses thousands of programmers. In Java, this represents the object itself, does it apply the same rule here?

This or that?

In most cases, the value of this is determined by how a function is called. This is not assigned a value until an object invokes the function where this is defined. So a very simple rule is always know how your function is invoked .
Consider the following example:

1
2
3
4
5
6
7
var a = 1;
function foo() {
console.log(this.a);
}
foo(); // 1

To understand why foo() return 1, can you find out where foo() is called? Actually it is called in global scope, a.k.a, called by the global window object. And hence this will refer to the window object, and find the value of variable a, 1.

How about this example:

1
2
3
4
5
6
7
8
var a = 1;
var obj = {
a: "not 1",
foo : function() {
console.log(this.a);
}
}
obj.foo(); // "not 1"

In this case, foo() is called by obj. So this will refer to the obj object. So this.a will try find a variable from obj and hence evaluated as “not 1”;

To find more about this keyword, checkout this book

Back to our question, now we know foo() is called in global scope, and hence this will refer to window object. So is it true that it will also alert 4 as last question since it’s the same as getName()?
Well, 4 is still incorrect. Look more carefully,

1
2
3
4
5
6
function Foo() {
getName = function() {
alert(1);
};
return this;
}

Calling Foo() will do another thing, which is assigning an anonymous function to getName variable. What is important here is this getName variable does not come with any declaration. The key takeaway here is that if an variable is used without any declaration, it will by default defined in the global scope, a.k.a window object. But we already have that getName in global scope! Therefore, it will overwrite the getName variable defined in global scope. And hence, it will actually alert 1 .

Next, we now call the global defined getName variable again. Since it got overwritten when we invoke Foo().getName();, it will alert 1 as well. This is quite tricky in my opinion.

Next three lines are about operator precedence and new keyword. You can find the priority table at here

1
2
3
new Foo.getName();
new Foo().getName();
new new Foo().getName();

For first one new Foo.getName();, from the table we know that member access (.) precedes the keyword new. So it is equivalent to new (Foo.getName)(). We are using the Foo.getName function as a constructor, and hence 2 will be alerted.

Things are getting more interesting at new Foo().getName();. This is equivalent to (new Foo()).getName(). We use Foo as the constructor and create a new Foo object. Then we invoke the prototype function defined for Foo object in

1
2
3
Foo.prototype.getName = function() {
alert(3);
};

and hence 3 will be alerted.

Finally, apply the same rule, new new Foo().getName(); is equivalent as new ((new Foo()).getName)();. An instance of Foo will be created. And we use its getName function as the constructor. So again, 3 will be alerted.

Conclusion

As you can see, such a simple question (at least it looks simple at first) actually tests a lot of important topics of JavaScript. Unless you understand them very well, you may easily make mistakes. I think the following books would help you to understand JavaScript better: