0

Javascript has the behavior where an error is not thrown on missing property access on objects, which is the cause of many pernicious bugs:

console.log("iPhone".missingProperty) // undefined

I'm wondering if this behavior is particularly abnormal for programming languages. Like the following will blow up in Ruby:

puts "iphone".missingProperty

As well as the following in Python:

print("iphone".missingElement)

Is this one of those quirks of Javascript that are a result of its hasty development, or was there reasoning behind this behavior?

  • 1
    No, countless languages do the same. – Konrad Rudolph Sep 17 '18 at 10:14
  • 2
    Lua is similar: iphone = {}; print(iphone.xyz) results in "nil" and not in an error. – Jan Sep 17 '18 at 12:23
  • @KonradRudolph name a few then? – jumbopap Sep 17 '18 at 15:04
  • @jumbopap Most “scripting” languages for starters; Perl, R, Lua, PHP … – Konrad Rudolph Sep 17 '18 at 15:11
3

JavaScript is fairly unique in that objects literally are dicts/hash-tables. There is no difference between a property access via dot notation object.field or bracket notation object['field']. This syntax is defined as always returning a Reference value even if no such entry exists, and this value may be undefined.

For hash tables in various languages, there's a wide difference in whether accessing a missing key returns a default value or raises an exception. E.g. in Perl $hash{$key} will return undef on missing keys. Other languages support both throwing and default-value accesses:

  • In C++, map[key] will create an entry with a default value, whereas map.at(key) will throw an exception
  • In Python, dict[key] will raise a KeyError, but dict.get(key) will return None.

JavaScript uses the same approach as in Perl that missing entries return a special value. This approach has the practical advantage that it can use the same machinery for lvalues and rvalues. In programming languages, an lvalue describes something that can be assigned to (e.g. variables). The left hand side of an assignment lvalue = rvalue must be an lvalue, i.e. a valid assignment target.

The return value of an property access in JavaScript is exactly such an lvalue (which it calls Reference). This reference stores the base object and the property name. If the reference is used as an rvalue to access the enclosed value, the property value or undefined is returned. But if the reference is used as an lvalue (assignment target), then a new entry with the given name can be created in the base object. This is described as the PutValue abstract operation in 6.2.3.2.

Note that this describes the abstract JavaScript virtual machine in the standard. A real implementation will optimize those steps away and won't actually create a Reference value. As a consequence, no such references can be passed around (unlike e.g. in C++ and to some degree in Perl).

See also:

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.