我在JavaScript面向对象和可分配的#34;范例。所以我过着幸福的生活,直到...
var x = {};
x.field = true;
x.field.netType = "System.Boolean";
alert(x.field.netType);
它编译,但警报一直给予“未定义”#。为什么!?
答案 0 :(得分:19)
JavaScript中的基元(字符串,数字,true
和false
)是不是对象。但是,当它们与.
或[]
一起使用时,就好像它们是对象一样,语言通过隐式构造它们的对象包装器来强制执行。
在你的例子中,发生了什么。对对象属性的赋值确实有效,因此没有错误,但是那个包装器对象立即被丢弃。
另一方面:
var x = {};
x.field = new Boolean(true);
x.field.netType = "System.Boolean";
alert(x.field.netType);
(我不建议实际这样做;使用由原始包装类型制作的对象往往会产生奇怪的效果,因为这些值会传播到不期望它们的代码中。)
答案 1 :(得分:10)
x.field = true;
x.field.netType = "System.Boolean";
实际上正在运作
x.field
这是一个原始的布尔值正在内部转换为对象,但我们没有它的引用,所以立即它变成垃圾。如果我们存储x.field
的引用,以便它不是垃圾,我们可以得到值。像这样....
x.field = true;
var y = x.field.netType = "System.Boolean";
alert(y);
如果你这样编写代码
var x = {};
x.field = {};
x.field.netType = "System.Boolean";
alert(x.field.netType);
然后它会起作用。
在你的代码中,这一行x.field.netType = "System.Boolean";
将在`strict mode
`//Cannot assign to read only property 'netType' of true`
为什么此行x.field.netType
提供undefined
这种类型的对象只是包装器,它们的值是它们包装的原语,它们通常会根据需要强制降低到该值。
JavaScript很容易在primitives and objects
。
var a = 'Intekhab';
a.length;//In this case the string value is coerced to a string object in order to access the property length.
var Twelve = new Number(12);
var fifteen = Twelve + 3; // In this case Object Twelve is coerced to a primitive value.
fifteen; //15
如果JavaScript检测到尝试将属性分配给基元,它确实会将基元强制转换为对象。这个新对象没有引用,将立即成为垃圾收集的饲料。
var primitive = "september";
primitive.vowels = 3;
//new object created to set property
(new String("september")).vowels = 3;
primitive.vowels;
//another new object created to retrieve property
(new String("september")).vowels; //undefined
答案 2 :(得分:5)
x.field
是一个布尔值;布尔值是基元并且是只读的。当您尝试将值分配给x.field.netType
时,您尝试修改x.field
的值。 Pointy的答案主要解释了这一点。
在正常情况下' JavaScript模式,这导致值只是undefined
。
为什么评论中有人提出严格模式(你应该肯定正在使用)的原因是严格模式会抛出错误通知您正在尝试将值分配给只读值并阻止您执行此操作,而不是在访问该属性时以静默方式返回undefined
。
'use strict';
var foo = true;
foo.bar = 'qux'; // this line will throw an Error
根据Pointy的例子,实际上错误,至少在Node 4.0上。我不知道DJ引擎Pointy正在使用什么,但它运行不正常。
> (function() { 'use strict'; (true).x = 0; })()
TypeError: Cannot assign to read only property 'x' of true
at repl:1:38
at repl:1:45
at REPLServer.defaultEval (repl.js:154:27)
at bound (domain.js:254:14)
at REPLServer.runBound [as eval] (domain.js:267:12)
at REPLServer.<anonymous> (repl.js:308:12)
at emitOne (events.js:77:13)
at REPLServer.emit (events.js:169:7)
at REPLServer.Interface._onLine (readline.js:209:10)
at REPLServer.Interface._line (readline.js:548:8)