Почему "foo".bar = 42; throw 'TypeError' в строгом режиме в ES6?
Согласно спецификации ES5.1, программа "use strict;" "foo".bar = 42;
"use strict;" "foo".bar = 42;
вызывает создание объекта String
, присваивает ему свойство и затем удаляет объект, что не приводит к наблюдаемым эффектам, включая любые исключения. (Отсутствие эффекта можно подтвердить, попробовав его в ES5-совместимой реализации JS, как в Opera 12.)
В современных реализациях JS он вместо этого TypeError
- попробуйте:
"use strict"; "foo".bar = 42;
Ответы
Ответ 1
Я предполагаю это здесь:
http://www.ecma-international.org/ecma-262/7.0/#sec-ordinaryset
9.1.9.1. OrdinarySet (O, P, V, Receiver)
[...]
4.b. Если Type (Receiver) не Object, верните false.
(Ранее называемый [[Set]], в ES6 §9.1.9.)
Хотя PutValue
продвигает base
к объекту, она не делает то же самое с приемником - GetThisValue(V)
все еще вызывается на исходном V
(с примитивной базой). Таким образом, GetThisValue
возвращает примитив, OrdinarySet.4b
не может назначить только что созданный ownDesc
и возвращает false
, а это в свою очередь заставляет PutValue.6d
бросать TypeError, если ссылка строгая.
Соответствующая часть V8, похоже, следует той же логике:
Maybe<bool> Object::AddDataProperty(....
if (!it->GetReceiver()->IsJSReceiver()) {
return CannotCreateProperty(...
https://github.com/v8/v8/blob/3b39fc4dcdb6593013c497fc9e28a1d73dbcba03/src/objects.cc#L5140
Ответ 2
Ответ @georgs кажется правильной интерпретацией ES6+, но похоже, что поведение тоже не новое. Из ES5.1 PutValue:
-
Иначе, если IsPropertyReference (V), то
а. Если HasPrimitiveBase (V) является ложным, то пусть put будет внутренним методом [[Put]] базы, иначе пусть будет специальный [[Put]] внутренний метод, определенный ниже.
б. Вызвать внутренний метод put, используя base, как его значение, и передать GetReferencedName (V) для имени свойства, W для значения и IsStrictReference (V) для флага Throw.
и в ссылке [[Put]]:
-
Else, это запрос на создание собственного свойства на переходном объекте O
а. Если Throw истинно, тогда выведите исключение TypeError.
Похоже, что Im, вероятно, неправильно читал что-то... но что еще может означать, что это скорее указывает на "это запрос на создание собственного свойства на переходном объекте O"?