为什么尝试在Javascript中为简单类型的属性赋值不会抛出异常?

时间:2010-12-10 09:33:53

标签: javascript

Javascript中的简单类型是不可变的,不是像对象那样的键控集合。为什么以下代码只返回赋值的值而没有抱怨?

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

第二个声明只返回'blaha'。但是,如果现在调用foo.newProperty,您自然会获得undefined因为简单类型不是哈希值。所以问题是,在尝试替换Python中元组中的值时,属性赋值的尝试不应该像获取TypeError一样抛出异常。或者是否有一些模糊的语法功能使foo.newProperty评估为意外的事情?

1 个答案:

答案 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.prototypeindexOf

更显着:

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

由于数字也会根据需要进行推广,因此完全可以接受。你必须使用parens - 例如,(4)而不仅仅是4 - 来满足语法(因为文字数中的.是小数点而不是属性访问者) ,虽然如果你想真的深奥,你可以使用4['toFixed'](2)。我不会。 : - )