In Chrome and Firefox,
typeof foo
evalulates to \'undefined\'
.
But
typeof (function() { return foo; })
Is this standard behavior?
Yes. typeof doesn't throw an error because it just returns a value as specified. However, as other answers have said, the code fails when evaluating the operand.
If so, it would be helpful to quote the relevant part of the ECMAScript standard.
When evaluating the function expression, an attempt to resolve the value of foo (so that it can be returned) will call the internal GetValue method with argument foo. However, since foo hasn't been declared or otherwise created, a reference error is thrown.
In the case of:
typeof (foo)
"(" and ")" are punctuators, denoting a grouping, such as a (possibly empty) parameter list when calling a function like foo(a, b)
, or an expression to be evaluated, e.g. if (x < 0)
and so on.
In the case of typeof (foo)
they simply denote evaluating foo before applying the typeof operator. So foo, being a valid identifier, is passed to typeof, per link above, which attempts to resolve it, can't, determines it's an unresolveable reference, and returns the string "undefined"
.
In the case of:
typeof (foo + 0)
the brackets cause the expression foo + 0
to be evaluated first. When getting the value of foo, a reference error is thrown so typeof doesn't get to operate. Note that without the brackets:
typeof foo + 0 // undefined0
because of operator precedence: typeof foo
returns the string "undefined"
, so +
becomes addition operator because one of the arguments is a string, it does concatenation (the string version of addition, not the mathematic version), so 0
is converted to the string "0"
and concatenated to "undefined"
, resutling in the string "undefined0"
.
So any time the evaluation of an expression with an unresolveable reference is attempted (e.g. an undeclared or initialised variable) a reference error will be thrown, e.g.
typeof !foo
throws a reference error too because in order to work out what to pass to typeof, the expression must be evaluated. To apply the !
operator, the value of foo must be obtained and in attempting that, a reference error is thrown.