No, this hasn’t changed (there’s something similar that’s changed, but not this; more below). Here’s the difference: If item
isn’t declared, then you’ll get the error about item
. If item
is declared but has the value undefined
, you’ll get the error about reading a property of undefined
. This has always been the case.
You mentioned Firefox. Firefox’s error messages for these two different conditions are confusingly similar. If the variable is undeclared, it says:
ReferenceError: item is not defined
But if the variable is declared and has the value undefined
, it says:
TypeError: item is undefined
Note the difference, but the extreme similarity. I would say Firefox’s error messages are poor in this regard. Chrome’s are more clearly distinct:
ReferenceError: item is not defined TypeError: Cannot read property 'property' of undefined
But that’s just the error message. The underyling issue, trying to read the value of an undeclared symbol, has always been an error.
Re the two answers you linked to: I’m sorry, but they were always wrong for the undeclared case (and right for the undefined
case), this is just something that people don’t understand well. If item
may be completely undeclared, you can’t use that idiom. You can use typeof
, though:
if (typeof item !== "undefined" && item.property)
typeof
is fine with undeclared symbols, but reading the value of an undeclared symbol is an error, as has been for as long as we’ve had JavaScript.
Here’s a question from 2011 about this. The accepted answer with a score of 1,016 talks about typeof
.
Here are examples of both cases:
Undeclared:
// Note that `item` isn't declared anywhere at all
try {
if (item.property) {
snippet.log("true");
}
}
catch (e) {
snippet.log((e.name || "Exception") + ": " + (e.message || String(e)));
}
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
Declared but has the value undefined
:
var item;
try {
if (item.property) {
snippet.log("true");
}
}
catch (e) {
snippet.log((e.name || "Exception") + ": " + (e.message || String(e)));
}
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
The similar thing that’s changed is how assigning to something that isn’t declared at all is handled:
item = "foo";
In loose mode, that’s an implicit global variable, even if the assignment is inside a function. In ES5’s strict mode, though, it’s an error.
But that doesn’t relate to reading the value of an undeclared variable, which was always an error, just writing to it.
1
solved Has something changed in Javascript implementations recently (or is it me)?