Reputation: 12341
Why when I try to access a variable that don't exist, javascript throw an exception but when I try to access a property that don't exist in an object, javascript returns an undefined
value?
For example, this case returns an undefined
value:
function Foo(){
console.log(this.bar);
}
Foo();
But, in this other example, javascript throw an exception:
function Foo(){
console.log(bar);
}
Foo();
ReferenceError: bar is not defined
Upvotes: 2
Views: 992
Reputation: 147403
Property resolution is fundamentally different to identifier resolution. The trivial answer is that ECMA-262 specifies that attempting to read a non–existent variable will throw an error, while attempting to read a non–existent object property does not, it just returns the special undefined value.
To get the reason, you'll need to aks Brendan Eich, who first developed JavaScript, on which ECMA-262 is based. However, a reasonable guess is that Brendan wanted to make JavaScript a simple language with loose typing, so rather than having to do something like:
if ( 'foo' in obj) {
/* do something with obj.foo */
}
every time you want to access a property for the first time, the language was made tolerant of attempts to access undefined properties.
On the other hand, applying the same approach to variables would have created more issues than is solves, so typeof
can be used to see if an identifier exists:
if (typeof foo != 'undefined') {
/* ok to use foo */
}
Otherwise, property and identifier resolution are quite similar. The difference is that the first proceeds from an object, along a string of internal [[Prototype]]
objects (the inheritance chain) and finally to the null
object, whereas variable resolution proceeds from the local variable object along a string of similar objects belonging to outer contexts (the scope chain) to the global object.
Upvotes: 1
Reputation: 2817
function Foo(){
console.log(window.bar);
}
Foo();
will also give you undefined
.
this.bar
means this["bar"]
Upvotes: 0
Reputation: 9706
As every object in JavaScript is a dictionary, also known as map in other languages, this.bar
is equivalent to this['bar']
, i.e. access to a value by a key. In most languages, e.g. in Java, returning null
, NULL
, or undefined
allows you to conditionally create this slot if it does not exist yet, without dealing with exceptions or any other side effects.
However, when you just write console.log(bar)
without specifying a context for the bar
, it would be impossible to create a reasonable pattern where returning undefined
would have a semantic meaning. There are multiple contexts, some of them dynamic, like global context window
in the browser, where the bar
might be defined during the runtime, so it cannot be a compile time error (as opposed to Java or C++). Hence runtime exception is thrown when variable name cannot be resolved.
Upvotes: 3