¿Por qué `"foo".bar = 42` 'throw' TypeError ' en modo estricto en ES6?


De acuerdo con la especificación ES5.1, el programa "use strict;" "foo".bar = 42; hace que se cree un objeto String, asigna una propiedad en él y luego tira el objeto, lo que no produce efectos observables, incluidas las excepciones. (La ausencia de efecto se puede confirmar intentándolo en una implementación JS compatible con ES5 como la de Opera 12.)

En las implementaciones JS modernas, lanza un TypeError en su lugar-pruébalo:

"use strict"; "foo".bar = 42;

Estoy bastante seguro de que el nuevo comportamiento es ordenado por la especificación ES6, pero a pesar de leer las secciones relevantes varias veces no puedo ver dónde se especifica que TypeError se lanzará. De hecho, las partes clave parecen ser invariable:

6.2.3.2 PutValue (V, W)#

  1. ReturnIfAbrupt( V).
  2. ReturnIfAbrupt( W).
  3. Si Type(V) no es Referencia, lanza una excepción ReferenceError.
  4. Sea la base GetBase (V ).
  5. Si IsUnresolvableReference (V) es true, entonces
  6. Else si IsPropertyReference (V) es true, entonces
    • a. Si HasPrimitiveBase (V) es verdadero, entonces
      • i. Assert: En este caso, base nunca será nulo o indefinido.
      • ii. Establecer basea toObject( base).
    • b. Sea sucedido? base .[[Set]](GetReferencedName(V), W, GetThisValue(V)).
    • c. ReturnIfAbrupt( succeeded).
    • d. Si succeeded es false y IsStrictReference( V) es true, lanza una excepción TypeError.
    • e. Retorno.

¿Dónde manda la especificación (ES6 o posterior) lanzar TypeError?

Author: cpcallen, 2018-04-06

2 answers

Supongo que está aquí:

Http://www.ecma-international.org/ecma-262/7.0/#sec-ordinaryset

9.1.9.1. OrdinarySet (O, P, V, Receiver)

[...]

4.b. Si Type(Receiver) no es Object, devuelve false.

(Anteriormente llamado [[Set]], en ES6 §9.1.9.)

Aunque PutValue promueve el base a un objeto, no hace lo mismo con el receptor {GetThisValue(V) todavía se llama en el original V (con una base primitiva). Por lo tanto, GetThisValue devuelve un primitivo, OrdinarySet.4b falla al asignar un ownDesc recién creado y devuelve false, y esto a su vez hace que PutValue.6d arroje un TypeError, siempre que la referencia sea estricta.

La parte correspondiente de V8 parece seguir la misma lógica:

Maybe<bool> Object::AddDataProperty(....
  if (!it->GetReceiver()->IsJSReceiver()) {
    return CannotCreateProperty(...

Https://github.com/v8/v8/blob/3b39fc4dcdb6593013c497fc9e28a1d73dbcba03/src/objects.cc#L5140

 16
Author: georg,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-04-12 09:15:10

La respuesta de@georg parece ser la interpretación correcta de ES6+, pero parece que el comportamiento tampoco es nuevo. De ES5. 1 PutValue :

  1. Else si IsPropertyReference (V), entonces

    A. Si HasPrimitiveBase (V) es false, entonces let put ser el [[Put]] método interno de base, de lo contrario let put ser el especial [[Put]] método interno definido a continuación.

    B. Llama al método interno put usando base como su valor this, y pasa GetReferencedName (V) para el nombre de la propiedad, W para el valor, e IsStrictReference(V) para la bandera de lanzamiento.

Y en el referenciado [[Put]]:

  1. De lo contrario, esta es una solicitud para crear una propiedad propia en el objeto transient O

    A. Si Throw es true, entonces arroja una excepción TypeError.

Se siente como que probablemente estoy malinterpretando algo but pero ¿qué más podría el más bien señaló " esto es un solicitud para crear una propiedad propia en el objeto transient O " be referring to?

 5
Author: Ry-,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-04-06 00:28:40