There are 8 language types in JavaScript:
- 7 primitive types: Undefined, Null, Boolean, Number, BigInt, String, and Symbol
- 1 non-primitive type: Object
Values of the primitive types are called primitive values and they cannot have properties.
Values of the Object non-primitive type are called objects an they can have properties.
When you try to assign a property named 'bar'
to a variable foo
, like so:
foo.bar = 'abc';
then the result will depend on the type of the value of foo
:
(a) if the value of foo
is of the type Undefined or Null, then an error will be thrown,
(b) if the value of foo
is of the type Object, then a named property 'bar'
will be defined on the object foo
(if necessary), and its value will be set to 'abc'
,
(c) if the value of foo
is of any other type, then a TypeError
will be thrown in strict mode: “can't assign to property "bar"
on foo
: not an object”. In loose mode, the above assignment operation will be a no op. In either case, the variable foo
will not be changed in any way.
So, as you can see, assigning properties to variables only makes sense if those variables are objects. If that is not the case, then the assignment will either do nothing at all, or even throw an error.
In your case, the variable test
contains a value of the type String, so this:
test.test = "test inner";
does nothing at all.
However, since ES5 introduced accessor properties, there is an exception to what I've said above. Accessor properties allow us to define functions which are invoked whenever the property is either retrieved or set.
For instance:
var str = '';
str.prop;
Here str
is a variable holding a String value. Therefore, accessing a property of that variable should be a no-op (str.prop
merely returns undefined
). This is true with one exception: if String.prototype
contains a accessor property 'prop'
with a defined getter, then that getter will be invoked.
So, if this is defined:
Object.defineProperty( String.prototype, 'prop', {
get: function () {
// this function is the getter
}
});
then this
str.prop;
will invoke that getter function. This also works in strict mode.
Live demo: http://jsfiddle.net/fmNgu/
However, I don't think that adding accessor properties to the built-in prototypes would be a good practice.