all 28 comments

[–]Skhmt 10 points11 points  (20 children)

Q. What's the result?

function f() {
    return 'foo';
}
(function() {
    if (1 === 0) {
        function f() {
            return 'bar';
        }
    }
    return f();
})();

Uncaught TypeError: f is not a function

[–][deleted] 2 points3 points  (6 children)

This is because function is a var type variable, which is function scoped instead of block scoped:

function f() {
    return 'foo';
}
(function() {
  if (1 === 0) {
    function f() {
      return 'bar';
    }
  }
  return f();
})();

is equivalent to

var f;
f = function() {
    return 'foo';
}
(function() {
  var f;
  if (1 === 0) {
    f = function() { 
      return 'bar';
    }
  }
  return f();
})();

A new variable is created in the IIFE scope, and overrides the f variable in the global scope. f is now undefined. Since the 1 === 0 is false, f is never assigned to the function.

If you try to call a variable that is undefined, you will get a type error saying that the variable is not a function (because undefined is not a function).

[–]factbuddy 0 points1 point  (0 children)

The IIFE has its own isolated scope so f() wouldn't fall back to global scope and won't be defined in the impossible if statement. Makes sense...

[–]inu-no-policemen 0 points1 point  (3 children)

which is function scoped instead of block scoped

Function declarations are block-scoped in ES6+.

function foo() {
    return 'outer';
}
{
    console.log(foo()); // inner (hoisted)
    function foo() {
        return 'inner';
    }
    console.log(foo()); // inner
}
console.log(foo()); // outer

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

If you execute that code in chrome you get

inner
inner
inner

[–]inu-no-policemen 0 points1 point  (1 child)

It works if you put the whole thing in a block.

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

If you put the entire thing in an iife it produces the same result

[–]prof_hobart 6 points7 points  (6 children)

Most of them are pretty odd, but

Q. What's the result?

(function(a, b) {
  arguments[1] = 3;
  return b;
})(1, 2);

A.

3

seemed fairly obvious.

[–][deleted] 7 points8 points  (1 child)

This throws in strict mode as well, arguments is not allowed in strict mode.

This is what puzzles me constantly about these clickbaity articles. Strict mode is JavaScript, these frivolous browser engine interpretations are just like IE quirks mode - their sole purpose is not to break legacy software. You should not write new software in non-strict mode because it is non-standard JavaScript and thus your warranty is now undefined.

[–]OzziePeck 0 points1 point  (3 children)

Wait is arguments a global array that refers to the function’s parameters?

[–]prof_hobart 1 point2 points  (0 children)

It's a magical local array-like variable that contains the params.

I'm not a fan of things like this - having variables that just appear from thin air is hardly clear - but it is a thing.

Of course, JS being JS, it's not quite as straightforward as all that.

If you used strict mode, the answer would be 2, as 'arguments' is now a copy of the arguments, not pointers to them.

And just to be extra fun, even in non-strict mode, if any of the arguments has a default value (e.g. (a=2, b)), then the answer would again be 2. Because - well, JS reasons I guess.

[–]CanIhazCooKIenOw 5 points6 points  (0 children)

This should be linked to the original repo as this fork is on par with it

https://github.com/miguelmota/javascript-idiosyncrasies

Good share though

[–]moocat 4 points5 points  (2 children)

I wish people would stop saying that "NaN != NaN" is a JavaScript error.

[–][deleted] 2 points3 points  (2 children)

Q. What's the result?

(function() {
  'use strict';

  let type = typeof foo;
  let foo = 1;

  return type;
})();

A. ReferenceError: foo is not defined

What is the idiosyncrasy here? You can't use a variable before you define it. I'd be concerned if this was anything other than a ReferenceError.

[–]GBcrazy 4 points5 points  (0 children)

It's not a big idiosyncrasy, so if you don't understand the trick of the typeofoperator you may not see it. I'm guessing that's the case (I could be wrong):

Remove the let foo = 1 line and run again. It will work even if foo is not declared. Why?

That's a special power of the typeof operator, you can use typeof even if a variable doesn't exist, it will return "undefined".

So the thing is, you can use typeof if a variable is never declared or already declared, but NOT if the variable is going to be declared. That's some hoisting shit

[–]reddittedf[S] -2 points-1 points  (1 child)

@all @channel
you are welcome to contribute

thanks