Answering Nicholas Zakas' JavaScript quiz

A current meme that's floating around the JavaScript geek corner of the internet is setting quizzes on some of the more unusual aspects of JavaScript. This time round Nicholas Zakas is providing the entertainment, so I thought I'd provide some answers. Let's get started:

Question 1

Question 1 looks like this:


var num1 = 5,
num2 = 10,
result = num1+++num2;

var num1 = 5,
num2 = 10,
result = num1+++num2;

We're asked what the values of result, num2 and num1 are. First, let's deconstruct what that +++ is doing. There is no +++ operator in JavaScript - instead we have a num1++ followed by a + num2.

JavaScript has two ways of incrementing a number by 1 - we can either put the ++ before the variable or after it. The variable is incremented either way - the only difference is what is returned. ++10 returns 11, whereas 10++ returns 10:


var a = 10;

var b = a++; //a is set to 11 now, but b is set to 10
var c = ++a; //a is set to 12 now, c is also set to 12

var a = 10;

var b = a++; //a is set to 11 now, but b is set to 10
var c = ++a; //a is set to 12 now, c is also set to 12

So 'result' is the sum of num1++ (which is 5) and num2, which is 10, so result equals 15. num2 remains at 10 as it was not modified. num1 is now equal to 6 because we incremented it by 1, though the incrementation did not affect the sum passed to result.

Question 2


var x = 5,
o = {
x: 10,
doIt: function doIt(){
var x = 20;
setTimeout(function(){
alert(this.x);
}, 10);
}
};
o.doIt();

var x = 5,
o = {
x: 10,
doIt: function doIt(){
var x = 20;
setTimeout(function(){
alert(this.x);
}, 10);
}
};
o.doIt();

We're asked what is alerted. This is mostly smoke and mirrors - there's some indirection with all the duplicate names but the important thing here is the setTimeout. The function we pass to setTimeout gets run in the global scope, meaning 'this' refers to the window object. Declaring x as a variable in the global scope (var x = 5) is the same as setting window.x = 5, so 5 is alerted.

Question 3


var num1 = "10",
num2 = "9";

var num1 = "10",
num2 = "9";

We're asked:

  • What is the value of num1 < num2?
  • What is the value of +num1 < num2?
  • What is the value of num1 + num2?
  • What is the value of +num1 + num2?

This question is all about type casting.

  • num1 < num2 is true - if both operands are strings JavaScript will compare them alphabetically, and "10" is lower alphabetically than "9"
  • +num1 < num2 is false - placing a "+" operator before a string casts it into a number, so we're actually testing 10 < "9". When testing a mixture of numbers and strings like this, everything is cast into a number, so we're testing 10 < 9, which is false
  • num1 + num2 === "109" - the plus sign can mean both addition and concatenation, depending on the operand types. Here we have 2 strings so we're concatenating them together
  • +num1 + num2 === "109" also - again we're casting num1 into a number, but the + operator means concatenation if at least one operand is a string

The confusion around this comes largely from the fact that the plus sign is used for both addition and concatenation in JavaScript. This causes the engine to have to test the typeof each operand and cast accordingly. All of the other math operators (e.g. /, *, % etc) cast both operands to numbers.

Question 4


var message = "Hello world!";

var message = "Hello world!";

We're asked:

  • What is the value of message.substring(1, 4)?
  • What is the value of message.substr(1,4)?

substring and substr do similar things. The first argument to each is the character index to start from, but whereas substring's second argument is the character index to end at, substr's second argument is the number of characters to return. Therefore message.substr(1, 4) will return a string of length 4, whereas message.substring(1, 4) will return a string of length 3 (4 - 1):

  • message.substring(1, 4); //"ell"
  • message.substr(1, 4); //"ello"

Question 5


var o = {
x: 8,

valueOf: function(){
return this.x + 2;
},
toString: function(){
return this.x.toString();
}
},
result = o < "9";
alert(o);

var o = {
x: 8,

valueOf: function(){
return this.x + 2;
},
toString: function(){
return this.x.toString();
}
},
result = o < "9";
alert(o);

We're asked the value of 'result', and what gets alerted. This requires an understanding of the special valueOf and toString functions available on every object. These functions are used internally by the JavaScript engine to pull out the best representation of an object's value based on the situation.

When alerting a value, we want a string representation so toString is called. When comparing the value to another object, valueOf is called instead. So alert(o) alerts "8", and result is set equal to the result of 10 < "9". The JavaScript engine will decide when to use which option, or we can specify it ourselves:

var num1 = 8, num2 = 9;

num1 + num2; //17
num1.toString() + num2.toString(); //"89"
num1.valueOf() + num2.valueOf(); //17
var num1 = 8, num2 = 9;

num1 + num2; //17
num1.toString() + num2.toString(); //"89"
num1.valueOf() + num2.valueOf(); //17

The 'result' assignment needs a little explanation. First, the engine calls valueOf on the object, which returns 10. Second, because one of the operands to the < operator is a number, the other is also cast into a number, so we are testing 10 < 9, which returns false. We could instead force it to use toString: o.toString() < "9" returns true.

Quizzes like this are great for getting your teeth into some of the guts of JavaScript, but don't mistake them for a good way to write code. The point is to demonstrate how quirky JS code can be unless you write it in a sensible way.

Share Post:

What to Read Next

If you enjoyed dissecting JavaScript quirks in this quiz, you might appreciate exploring the difference between function expressions and statements to deepen your understanding of JavaScript functions. Additionally, consider reading about the potential pitfalls of the JavaScript module pattern for insights into common design patterns and their impact on code flexibility.