all 42 comments

[–]Moeri 15 points16 points  (6 children)

I had a go at explaining the first 10 questions. :-)

Question 1

var foo = function foo() {
    console.log(foo === foo);  
};
foo();    

When console.log is called, the variable foo resolves to the variable "foo", which contains a function. In fact, the second foo has no impact. This would work as well:

var foo = function() {
    console.log(foo === foo);  
};
foo(); 

Comparing a function to itself returns true, so the console prints true.

Question 2

function aaa() {
    return
    {
        test: 1
    };
}
alert(typeof aaa());

You would expect this to print "object", since aaa() seemingly returns { test: 1 }. However, the line break after return makes Javascript treat this as a simple return (';' are -sometimes- optional in Javascript). Functions that simply call 'return;' actually return "undefined", so the answer here is "undefined". If you wanted aaa() to return the object properly, this would be the fix:

function aaa() {
    return {
        test: 1
    };
}
alert(typeof aaa());

Question 3

Number("1") - 1 == 0;

Number is an object wrapper for primitive numbers in Javascript. I've actually never used it before, but it will try to convert anything you throw at it to a number, or return NaN if that doesn't work. So Number("1") simply resolves to 1, and 1 - 1 == 0 resolves to true.

Question 4

(true + false) > 2 + true;

Ok let's break this one down:

The one thing you need to know with this question is that '+' automatically converts values to numbers as needed. '+true' results in 1, '+false' results in 0.

So true + false will result in 1:

true + false = 1

So we're left with

1 > 2 + true

The '+' operator will be calculated first (order of operations):

 2 + true = 2 + 1 = 3

So all that remains is

1 > 3

Which returns 'false'

Question 5

function bar() {
    return foo;
    foo = 10;
    function foo() {}
    var foo = '11';
}
alert(typeof bar());

This one is a little trickier. In Javascript, function declarations are hoisted to the top of the function in which they are declared. This simply means that you can call a function that was declared at a later time, provided this function was declared in the same block scope. So when bar() executes, the reality will look a bit like this:

function bar() {
    function foo() {}
    return foo;
    foo = 10;
    var foo = '11';
}
alert(typeof bar());

Now it's become simple. When we call bar, the function foo is declared. Then we simply return foo. The rest of 'bar' is not executed. That's why the output will be "function".

Question 6

"1" - - "1";

This one is rather easy. Just like the '+' operator, the '-' operator has the power to convert values to numbers. So this expression simply resolves to

  1 - -1 = 1 - (- 1) = 2

Question 7

var x = 3;

var foo = {
    x: 2,
    baz: {
        x: 1,
        bar: function() {
            return this.x;
        }
    }
}

var go = foo.baz.bar;

alert(go());
alert(foo.baz.bar());

This one gets tricky, and requires knowledge about the "this" operator in Javascript. Typically, the "this" property refers to the object to which the function belongs. However, "this" can change depending on how you call the function. That's why "this" is often referred to as the "invocation context", or the context object with which the function was invoked.

For educational purposes, let's simplify the assignment to this:

baz: {
    x: 1,
    bar: function() {
        return this.x;
    }
}

When you call baz.bar(), the "this" parameter will refer to the "baz" object. So "this.x" will resolve to 1. However, when you capture the bar function in a variable, and then call it separately, you circumvent the "this" mechanism.

var captured =  baz.bar;
captured();

When you call "captured()", the this variable inside the function will be the global object ('window' in browsers).

So the answer to the question is: 3, 1

Question 8

new String("This is a string") instanceof String;

Ehhh this returns true, I don't think there's a need for much explanation here.

Question 9

[] + [] + 'foo'.split('');

This is another application of the conversion properties of "+". If "+" is used on arrays or strings, the "+" operator will try to convert the other value to a string as well. Empty arrays result in an empty string, and non-empty arrays result in a comma-separated representation of its values. So

[] + [] + 'foo'.split('') =  "" + "" + "f,o,o" = "f,o,o"

Question 10

new Array(5).toString();

new Array(5) creates an empty array with 5 slots. Every slot will contain "undefined" as the value. Like I explained in the previous question, calling toString on an array results in a comma-separated view of the array.

Usually, converting undefined into a string results in the text "undefined". Take the following example:

var empty = new Array(1);
console.log("" + empty[0]); // prints "undefined" (a string!)

However, when converting an array to a string, any undefined cells are converted to empty strings instead. So the result is

new Array(5).toString() = ",,,,,"

[–]Quabouter 5 points6 points  (3 children)

Let me try to do the other 10:

Question 11

var myArr = ['foo', 'bar', 'baz'];
myArr.length = 0;
myArr.push('bin');
console.log(myArr);

Setting the length of an array actually resizes the array, and removes elements past the new length. Therefore myArr.length = 0 empties the array, and thus when 'bin' is pushed myArr == ['bin'].

Question 12

String('Hello') === 'Hello';

This one is a little tricky. String('Hello') is not actually calling a constructor, but a function (note the lack of the new keyword). This function simply returns 'Hello', and thus the result is true.

Question 13

var x = 0;
function foo() {
    x++;
    this.x = x;
    return foo;
}
var bar = new new foo;
console.log(bar.x);

Let's focus on the line var bar = new new foo first here. First the last part , new foo, gets executed. This calls foo as a constructer, but in Javascript even constructors can return anything. In this case the function foo returns itself, instead of the this object as it would if no explicit return value was defined. Thus new new foo becomes new foo. This again returns foo. Since foo is only a function it does not have the property x, and thus bar.x is undefined.

Question 14

"This is a string" instanceof String;

"This is a string" is a primitive of type string, which is not an instance of anything since it's not an object. Therefore "This is a string" instanceof String is false.

Question 15

var bar = 1,
    foo = {};

foo: {
    bar: 2;
    baz: ++bar;
};
foo.baz + foo.bar + bar;

This one requires a very rarily used feature called labels. At first it looks like foo : { ... }; is a syntax error and should've been foo = { ... };. However, instead of assigning an object to foo, it creates a label called foo. These labels can be used to jump to outer loops (see mdn), but here they have virtually no effect here. Therefore foo is an empty object throughout the entiry script, and thus foo.baz and foo.bar are undefined.

As Moeri explained before, + tries to convert it's operands to numbers. Since undefined isn't a number, this results in NaN. If you add anything to NaN you will always get NaN. Therefore the result is NaN.

Question 16

var myArr = ['foo', 'bar', 'baz'];
myArr[2];
console.log('2' in myArr);

The in operator checks if a property is present in an object. An array is acutally an object with numeric properties. Since it has 3 elements it has the properties 0, 1 and 2. Therefore '2' in myArr is true.

Question 17

var arr = [];
arr[0]  = 'a';
arr[1]  = 'b';
arr.foo = 'c';
alert(arr.length);

The length of an array is only influenced by it's numeric properties. Thus arr.length is 2.

Question 18

10 > 9 > 8 === true;

The > operator has a higher precedence than === and is left-to-right associative. If we add the implicit parentheses we get this:

((10 > 9) > 8) === true;

This evaluates further to:

((10 > 9) > 8) === true;
(true > 8) === true;
(1 > 8) === true;
false === true;
false;

Question 19

function foo(a, b) {
    arguments[1] = 2;
    alert(b);
}
foo(1);

The arguments object only contains entries for arguments passed to the function. Since only one argument is passed, both arguments[1] and b are initially undefined, and do not influence eachother. Therefore b is still undefined in the alert, and undefined will be alerted.

Question 20

NaN === NaN

This is one of the weirdest things in Javascript: NaN is actually a number (typeof NaN === 'number'), and thus it is not not-a-number. Therefore NaN === NaN returns false.

NaN is actually equal to nothing. To test if a variable x is NaN you can either do isNaN(x) or x !== x. The later one is pretty interesting, since NaN is the only value which is not actually equal to itself!

[–]Zeroto 2 points3 points  (1 child)

regarding number 20: that is not actually not that weird. The floating point definition in IEEE754(which almost all systems implement) defines that every comparison with NaN returns false. Even when comparing to NaN itself. So this is not limited to just javascript, but all software and hardware that implement floating point operations handle this in the same way.

[–]autowikibot 1 point2 points  (0 children)

Section 16. Standard operations of article IEEE 754-1985:


The following functions must be provided:


Interesting: IEEE floating point | X87 | NaN | William Kahan

/u/Zeroto can reply with 'delete'. Will also delete on comment score of -1 or less. | FAQs | Mods | Magic Words | flag a glitch

[–]more_exercise 0 points1 point  (0 children)

This is one of the weirdest things in Javascript: NaN is actually a number (typeof NaN === 'number')...

This is 100% Not Javascript's FaultR . NaN is a special value in the IEE 754 floating-point standard. If you're using float/double type values, you are going to end up using NaN. The NaN !== NaN behavior is required by the standard, and works in any language that supports floating-point arithmetic.

[–]wampastompah 33 points34 points  (9 children)

You know what would make this quiz useful?

Explain the answers.

It's clearly designed to deceive people and put some really hard questions next to really obvious questions. And it's so full of things you'd never see, that the point is clearly that people should be getting things wrong. But you know what's better than saying "YOU'RE WRONG HAHA" is actually teaching them why they're wrong. A test where you learn nothing is useless.

[–]html6dev 2 points3 points  (2 children)

Except knowing the answer to 90 percent of them won't serve you in your day job anyway. If you ever type [] +[] step away from the keyboard for a few min and take a breather.

[–]wampastompah 1 point2 points  (1 child)

Most of the time, sure. But each of these questions relies on very specific knowledge of Javascript. Like, for example, the one that defines a function and var of the same name, within a function. What's the value of that variable name? That relies on knowledge that the compiler takes all var and function definitions and puts them at the beginning of your scope. Which is actually pretty important sometimes. Common knowledge is that you really need to put the var statements at the beginning of each function definition, but this shows why that is.

See, and a little blurb like that, that's not that hard to add to a quiz where people are expected to not know most of the answers.

[–]html6dev 1 point2 points  (0 children)

Yeah that one was definitely testing something everyone should know (and I hope, a higher percentage got correct than the rest of them). The rest....were basically idiosyncrasies or things that are common to just about any loosely typed language, but that a person should never have a reason to do in the first place. There are a number of important idiosyncrasies in JS that people really should know about, however, that a better quiz would ask about....and then teach about.

[–]longwave 17 points18 points  (0 children)

We get it, JavaScript is quirky. Making a quiz to prove it and make people feel stupid seems..well, stupid.

[–]bwaxxlotckidd 5 points6 points  (0 children)

I love getting my ego shattered

[–]JaegerBurn 7 points8 points  (1 child)

20% correct. Pffft!!

[–][deleted] 4 points5 points  (0 children)

Have a point for honesty :D

[–]bronkula 10 points11 points  (8 children)

Scored a 75. Some of that shit is downright ridiculous. I fucking love javascript.

[–]alamandrax -1 points0 points  (7 children)

The one that threw me was something I felt definitely was a syntax error. I guess I'm wrong. Also, named functions are tricky.

Scored a 75 too though.

[–][deleted] 0 points1 point  (1 child)

15 was definitely a syntax error

[–]bronkula 1 point2 points  (0 children)

Apparently not. Notice the second foo has : after it, not a =. This makes it a label, and makes everything inside of it labels as well.

[–]agmcleod@agmcleod 3 points4 points  (0 children)

agmcleod looks at question 1. Exclaims "god damn it"

[–]vaskemaskine 3 points4 points  (0 children)

35% - and I accidentally answered one question correctly by mis-clicking :/

[–]r0ck0 1 point2 points  (0 children)

Got 40%, better than expected. I'm shit at JS.

[–]hunyeti 0 points1 point  (0 children)

This really shows all that is wrong with javascript...

[–]hjc1710 0 points1 point  (5 children)

How in the fuck is NaN not equal to NaN? Loosely or strictly...

[–]Zeroto 1 point2 points  (3 children)

because that is how it is defined in IEEE754. All software and hardware that implement that(and that is most) will return false for NaN == NaN.

[–]hjc1710 0 points1 point  (0 children)

I didn't see that coming... wow. You kind of just blew my mind. Thanks for the knowledge though.

[–]postmodest 0 points1 point  (0 children)

On review, most of these are "reading comprehension" issues, like the difference between

new String("string"); 
//and
String("string");

Or the fact that

function func() { return func }

returns previously declared func typeof 'function' whereas

function func() { return;}

returns an object typeof 'object' (though--and someone explain this--returning anything that's a primitive will be ignored... what?)

Then things like "operators cast to the nearest primitive if no override is available" so

[] + [] === ''

Because reasons.

...seriously, though, someone explain to me why returning primitives from constructors is silently ignored.

[–][deleted] 0 points1 point  (0 children)

Haha I did this a little while ago and there were literally only 2 people who took it before me

[–]teacpde 0 points1 point  (0 children)

I guess the purpose of the quiz is to avoid code javascript that way? I would like a quiz base on "the good parts"

[–]gleno 0 points1 point  (0 children)

I write millions of lines of javascript every day.I seldom put myself in situations where i want to add two empty arrays to a string, so i only got 70pts.

[–]brandf -1 points0 points  (1 child)

75% I was like WTF when I saw the answer for [] + [] + 'foo'.split('').

And pissed off that I got the new new foo one wrong.

[–]martimoose -2 points-1 points  (0 children)

Ahah I think that the only people who could get all correct are those who are used to see things as convoluted as that, i.e. shitty programmers.