Why is the behavior of the undefined variable different from undefined property?

4

I've noticed this a long time ago in Javascript.

If I write a particular code where the variable is not defined in any scope, an exception is thrown:

console.log(preco)

Result:

  

Uncaught ReferenceError: price is not defined

But if I try to access an undefined property, no error is thrown, but only undefined is returned:

  var obj = {};

  console.log(obj.id); // undefined
  console.log(window.preco); // undefined

Why does JavaScript behave this way?

    
asked by anonymous 26.10.2016 / 15:55

3 answers

3

Because of the nature of the two.

The variable is something more concrete in the language, it must exist in the code, it has to verify and to know if it exists or not.

The property of an object looks like a variable, but it is not, is just a key in an array associative . There is no way for the JS interpreter to be sure whether it exists or not, there may be one hour, not another. Objects in JS are open for dynamic modification in their structure at any time.

obj.id

It's actually

obj["id"]

Of course there could be a way to detect the problem and generate an error, but resolve to be consistent with the table engine used in the associative array that is to consider that the element that does not exist is only undefined and does not generate an error. The way to know if a key exists is just compare with undefined .

So if you access the element in the table, no error occurs, even if it does not exist, it is just a key that does not exist at that moment. Dynamic typing languages have this advantage of being flexible and the disadvantage of being less robust and requiring the programmer to worry about doing it right, testing before use, either by unit tests, or by testing the code itself, if it can turn around if there is an error.

var obj = {
    a : 1
};
console.log(obj.a);
console.log(obj.b);
if (obj.b == undefined) {
    console.log("propriedade não existe");
}
obj.b = 2;
console.log(obj.b);
for (var chave in obj) {
  console.log(chave + " = " + obj[chave]);
}
    
26.10.2016 / 16:02
1

An undeclared variable is not listed in the VariableEnvironment .

In your example:

console.log(preco)

This means that the preco identifier is not resolved for any object stored in VariableEnvironment ; an exception indicating non-definition is generated ( $ident is not defined ).

A declared but uninitialized variable receives the default value undefined , which is both a property of the global object and one of javascript primitive types . In your example:

var obj = {};
console.log(obj.id);

The id property (which is nothing more than a key that points to a member of the property collection of the obj object) does not point to any objects.

However, the requested collection is not VariableEnvironment , but only the collection of properties: The value returned is the undefined global.

    
26.10.2016 / 16:22
0

I do not know exactly why this works, but what I noticed is that the exception of an undefined variable helps us to find out if it exists or not, whether global or local.

try {
    aa
} catch(e) {
    // não existe
}

For object properties this makes it difficult to detect the presence of a property in old browsers (type MsIE6), but thanks to the in operator this makes it possible, with one exception.

Anyway, it would not make sense for a non-existent property to throw an exception, perhaps they wanted to avoid problems with expressions:

!!b

Only one exception to be thrown, the execution of that block for, unless there is a try/catch/finally to protect the exception.

Currently, to find out whether an object's property exists we need a native method or operator, the property can be undefined , any type of value. Object#hasOwnProperty resolves this, the in operator will do the same, but will deeply check if the specific property exists in the constructor properties, too.

Warning1: name of all properties of an object / function are converted to string;
Warning²: both functions and objects can save properties on itself;
Warning: all numeric values, strings, objects, functions, and booleans can be indexed . or [...] , minus null and undefined -

var a = {
    b: undefined
}

// Diz que a.b não existe
typeof a.b !== 'undefined'

// Diz que a.b existe
a in 'b'

// Diz que a.b existe
a.hasOwnProperty('b')

And this is the most commonly used way to check if a property exists:

// Se a.b for um valor verdadeiro,
// diz sim
!!a.b
    
26.10.2016 / 16:35