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

Sam*_*Sam 4 javascript

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

var foo = 'bar';
foo.newProperty = 'blaha';
Run Code Online (Sandbox Code Playgroud)

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

T.J*_*der 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"
Run Code Online (Sandbox Code Playgroud)

向基元添加属性但后来似乎没有工作的原因是转换仅用于表达式的目的.所以,如果我这样做:

foo.newProperty = 'blaha';
Run Code Online (Sandbox Code Playgroud)

foo变量中检索原始字符串值,然后从原语转换为表达式的对象,但用于表达式(我们还没有为变量赋予新值foo,毕竟,它只是从中检索的值)foo表达式已被更改为使表达式工作).如果我们想确保foo引用一个String 对象,我们必须这样做:

foo = new String(foo);
foo.newProperty = 'blaha';
Run Code Online (Sandbox Code Playgroud)

这种自动转换在规范中的第9节("类型转换和测试")和第11.2.1节("属性访问器")中有所涉及(尽管是通常的笨拙的规范说话风格).:-)

重新提出你的问题"......这种自动包装是否有充分的理由?" 下面:哦,是的.这种从原始到对象的自动升级非常重要.例如:

var foo = "bar";
alert(foo.length);
Run Code Online (Sandbox Code Playgroud)

基元没有属性,因此如果没有任何自动升级,则上面的第二行将失败.(当然,一个实现可以自由地进行优化,这样就不需要创建实际的对象,只要它的行为符合规范的外部要求.)同样:

var foo = "bar";
alert(foo.indexOf('a')); // alerts 1
Run Code Online (Sandbox Code Playgroud)

基元不是对象,因此它们没有原型链,那么该indexOf属性来自何处?当然,答案是原语被提升为一个String实例,而且String.prototype具有indexOf.

更显着:

alert((4).toFixed(2)); // alerts "4.00"
Run Code Online (Sandbox Code Playgroud)

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