Why doesn't trying to assign a value to a simple property type in Javascript throw an exception?

Simple types in Javascript are immutable and do not contain collections, such as objects. Why does the following code just return an assignment value without complaint?

var foo = 'bar'; foo.newProperty = 'blaha'; 

The second statement simply returns "blaha". However, if you now call foo.newProperty , you naturally get undefined because simple types are not hashes. So the question is not that trying to assign a property throws an exception the same way you get a TypeError when you try to replace a value in a tuple in Python. Or is there some kind of obscure syntax feature that makes foo.newProperty evaluate something unexpected?

+4
source share
1 answer

There is an unclear feature of the syntax that foo.newProperty . :-) Lines and numbers can be either primitives or objects, and the interpreter automatically converts from a primitive to an object (and vice versa) if it sees a need.

 var foo = 'bar'; // `foo` is a primitive alert(typeof foo); // alerts "string" var foo2 = new String('bar'); // `foo2` is an object alert(typeof foo2); // alerts "object" 

The reason that adding a property to the primitive works, but then it seems like it didn't work, is because the conversion is done only for the purpose of the expression. Therefore, if I do this:

 foo.newProperty = 'blaha'; 

The initial string value is extracted from the variable foo , and then converted from the primitive to an object for expression, but only for the expression (we did not assign a new value to the variable foo , after all, it's just that the value obtained from foo for the expression was changed so that make the expression work). If we wanted to make sure that foo refers to a String object, we must do this on purpose:

 foo = new String(foo); foo.newProperty = 'blaha'; 

This automatic conversion is discussed (bit) in Section 9 ("Converting and Type Testing") and Section 11.2.1 ("Property Accessors") into a specification , although in the usual inconvenient style of a specification .:-)

To your question "... is there a good reason for this automatic printing?" below: Oh yes. This automatic progression from the primitive to the object is quite important. For instance:

 var foo = "bar"; alert(foo.length); 

Primitives have no properties, so if there wasn’t any auto-promotion, the second line above failed. (Naturally, the implementation can be optimized in such a way that the creation of the actual object is not required if it behaves as the specification dictates from the outside.) Similarly:

 var foo = "bar"; alert(foo.indexOf('a')); // alerts 1 

Primitives are not objects, so they do not have a prototype chain, so where does this indexOf property indexOf ? And, of course, the answer is that the primitive is pushed to the String instance, and String.prototype has indexOf .

More sharply:

 alert((4).toFixed(2)); // alerts "4.00" 

Since the numbers also advance as necessary, this is perfectly acceptable for this. You should use parens - for example, (4) , and not just 4 - to satisfy the grammar (since . In the literal number is a decimal point and not an accessor property), although if you want to be truly esoteric, you can use 4['toFixed'](2) . I would not.: -)

+5
source

All Articles