开发者

Why can't I set properties of an array element (a string) in JavaScript?

var array = ['a', 'b', 'c'];
array[0].property = 'value';

a开发者_Python百科lert(array[0].property);   
alert(array[0].property = 'value');
alert(array[0].property);   

The result? undefined, 'value', then undefined

Why isn't this code working as expected?


The Array is irrelevant - you're trying to set a property on a primitive:

A data that is not an object and does not have any methods. JavaScript has 5 primitive datatypes: string, number, boolean, null, undefined. With the exception of null and undefined, all primitives values have object equivalents which wrap around the primitive values, e.g. a String object wraps around a string primitive. All primitives are immutable.

If you absolutely must use a property to carry this additional information around in a string, an alternative would be to use the object equivalent:

>>> var array = [new String('a'), new String('b'), new String('c')];
>>> array[0].property
undefined
>>> array[0].property = 'value'
"value"
>>> array[0].property
"value"

A potential gotcha to look out for if you do this and later need to detect that the value is a string:

>>> var a = ['s', new String('s')];
>>> a.map(function(s) { return typeof s; });
["string", "object"]
>>> a.map(function(s) { return s instanceof String });
[false, true]
>>> a.map(function(s) { return Object.prototype.toString.call(s) == '[object String]' });
[true, true]


Your array elements are string literals. JavaScript makes it seem like string literals are objects and have properties, but what's actually happening when you do array[0].property is that JavaScript is creating a temporary object for your string and assigning the property to that.

That's why the middle alert works correctly and the others don't. If you declared your array like:

var array = [new String('a'), new String('b'), new String('c')];

all three would work.


array[0] is a string, namely 'a' which you set in the first line and in JavaScript strings can't have additional properties.

If you want to use properties you have to use an object, for example a simple "empty" object: new Object() or short {}:

var array = [{}];
array[0].property = 'value';

alert(array[0].property);   
alert(array[0].property = 'value');
alert(array[0].property);   


This is due to a quirk (or performance restriction) in JavaScript -- the primitive types string, boolean, and number are immutable and any property assignment will just "vanish" (the single-inhabitant primitive types undefined and null will throw an exception on attempted property assignment). This is because these primitive values are not real objects (it makes them much more lightweight for the run-time).

However, for each of the primitive types there is a wrapper type: String, Boolean, and Number, respectively. The wrapper types are real objects and can have custom properties assigned.

While I would not do this, this will work (it sounds like an "icky design"):

var s = new String("foo");
s.bar = "hello"
alert(s.bar)

However, there are a number of odd quirks that this introduces -- typeof "" is "string" while typeof s is "object"*, and "" instanceof String is false while s instanceof String is true. Also, new Boolean(false) happens to be a truth-y value.

Happy coding.


*This will break a number of noddy library that do typeof x === "string"


You are trying to do 'a'.property = 'something'.

I'm not aware of any language that lets you assign a property of a string;

that would be like doing 12.property = 'something'.


In js strings and simple types stored/returned by value, not by reference.

If in your array you have some object, then it will work.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜