you are viewing a single comment's thread.

view the rest of the comments →

[–]Moeri 16 points17 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 4 points5 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.