Почему не все можно назначить в JavaScript?

Я был воспитан с "все в JavaScript объектно-ориентированной и назначаемой" парадигме. Поэтому я прожил свою счастливую жизнь, пока...

var x = {};

x.field = true;
x.field.netType = "System.Boolean";

alert(x.field.netType);

Он компилируется, но предупреждение продолжает давать met undefined. Почему!?

Ответы

Ответ 1

Примитивы (строки, числа, true и false) в JavaScript - это объекты не. Однако, когда они используются с . или [], как если бы они были объектами, язык обязывает, неявно создавая для них обертки объектов.

В вашем примере это произошло. Назначение свойства объекта действительно работало, поэтому ошибки не было, но этот объект-оболочка был немедленно выброшен.

С другой стороны:

var x = {};

x.field = new Boolean(true);
x.field.netType = "System.Boolean";

alert(x.field.netType);

(Я бы не советовал это делать, используя объекты, созданные из примитивных типов оберток, имеет тенденцию иметь странные эффекты, поскольку эти значения распространяются на код, который их не ожидает.)

Ответ 2

x.field = true; 
x.field.netType = "System.Boolean"; 

фактически работает.
 x.field, который является примитивным булевым значением, преобразуется в объект внутри, но у нас нет ссылки на него, поэтому он становится мусором. Если мы сохраним refrence 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

Ответ 3

x.field - это булево значение; Булевские значения являются примитивами и доступны только для чтения. Когда вы пытаетесь присвоить значение x.field.netType, вы пытаетесь изменить значение x.field. Пояснительный ответ в основном объясняет это.

В режиме "нормального" JavaScript это означает, что значение просто undefined.

Причина почему кто-то в комментариях предлагает строгий режим (который вы обязательно должны использовать) заключается в том, что строгий режим выдаст ошибку, сообщающую вам, что вы пытаетесь присвоить значение read- только значение и не позволяйте вам делать это, вместо того, чтобы молча возвращать undefined всякий раз, когда вы обращаетесь к этому свойству.

'use strict';
var foo = true;
foo.bar = 'qux'; // this line will throw an Error

В соответствии с примером Pointy он действительно делает ошибку, по крайней мере, на Node 4.0. Я понятия не имею, что использует JS-движок 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)