Javascript中的简单类型是不可变的,不是像对象那样的键控集合。为什么以下代码只返回赋值的值而没有抱怨?
var foo = 'bar';
foo.newProperty = 'blaha';
第二个声明只返回'blaha'。但是,如果现在调用foo.newProperty
,您自然会获得undefined
因为简单类型不是哈希值。所以问题是,在尝试替换Python中元组中的值时,属性赋值的尝试不应该像获取TypeError一样抛出异常。或者是否有一些模糊的语法功能使foo.newProperty
评估为意外的事情?
答案 0 :(得分:5)
语法的一个模糊特征使foo.newProperty
起作用。 :-)字符串和数字可以是基元或对象,如果需要,解释器将自动从基元转换为对象(反之亦然)。
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"
为一个原语添加一个属性,但后来似乎没有起作用的原因是该转换仅用于表达式的目的。所以,如果我这样做:
foo.newProperty = 'blaha';
从foo
变量中检索原始字符串值,然后从原语转换为表达式的对象,但仅表达式(我们尚未指定新的)毕竟,变量foo
的值只是从表达式的foo
检索到的值已被更改以使表达式起作用)。如果我们想确保foo
引用String
对象,我们必须故意这样做:
foo = new String(foo);
foo.newProperty = 'blaha';
这种自动转换在第9节(“类型转换和测试”)和the spec中的第11.2.1节(“属性访问器”)中有所涉及(尽管是通常的笨拙规范 - 说话风格) 。 : - )
重新提出你的问题“......这种自动包装是否有充分的理由?”下面:哦,是的。这种从原始到对象的自动升级非常重要。例如:
var foo = "bar";
alert(foo.length);
基元没有属性,因此如果没有任何自动升级,则上面的第二行将失败。 (当然,一个实现是可以自由优化的,这样就不需要创建实际的对象,只要它的行为符合外部规范。)同样:
var foo = "bar";
alert(foo.indexOf('a')); // alerts 1
原语不是对象,因此它们没有原型链,那么indexOf
属性来自何处?当然,答案是原语被提升为String
个实例,String.prototype
有indexOf
。
更显着:
alert((4).toFixed(2)); // alerts "4.00"
由于数字也会根据需要进行推广,因此完全可以接受。你必须使用parens - 例如,(4)
而不仅仅是4
- 来满足语法(因为文字数中的.
是小数点而不是属性访问者) ,虽然如果你想真的深奥,你可以使用4['toFixed'](2)
。我不会。 : - )