ejemplos - ¿Tiene javascript autobox?
javascript html (3)
En primer lugar, asumo que está hablando de la conversión automática de valores primitivos en objetos. Esto sucede en dos casos en JavaScript:
- Cuando pasa un valor primitivo como
this
valor a.call
o.apply
(.apply
no en modo estricto). - Cuando intenta acceder a una "propiedad" de un valor primitivo, por ejemplo,
"foo bar".split()
.
En el primer caso, la conversión es permanente, es decir, this
hará referencia a un objeto, en el segundo, la conversión solo tendrá lugar internamente durante la evaluación.
Si no está interesado en los detalles de la conversión, puede ignorar el resto de la respuesta.
1. Valor primitivo como this
Cuando se ejecuta una función y this
valor no es un objeto, se convierte en uno, al menos en modo no estricto. Esto se describe en §10.4.3 Introducción del código de función [espec.] En la documentación ECMAScript 5.1:
Los siguientes pasos se realizan cuando el control ingresa en el contexto de ejecución para el código de función contenido en el objeto de función
F
, un llamante proporcionó estethisArg
y una lista deargumentsList
proporcionados por el llamante:
- Si el código de función es un código estricto, establezca
ThisBinding
enthisArg
.- De lo contrario, si
thisArg
esnull
oundefined
, establezcaThisBinding
en el objeto global.- De lo contrario, si
Type(thisArg)
no esObject
, establezcaThisBinding
enToObject(thisArg
).
[...]
Como puede ver en el paso tres, el valor se convierte en un objeto llamando a ToObject
[spec] .
2. Acceso a la propiedad
Algo similar sucede cuando intenta acceder a las propiedades ( §11.2.1 Property Accessors [spec] ). La parte citada aquí explica cómo se evalúa la expresión foo[bar]
, es decir, cómo se evalúa el acceso de propiedad con la notación de corchete. La parte que nos interesa se aplica también a la notación de puntos.
La producción
MemberExpression : MemberExpression [ Expression ]
se evalúa de la siguiente manera:
- Deje que
baseReference
sea el resultado de evaluarMemberExpression
.- Deje que
baseValue
seaGetValue(baseReference)
.
[...]8. Devuelva un valor de tipo
Reference
cuyo valorbase
seabaseValue
y cuyo nombre de referencia seapropertyNameString
y cuyo indicador de modostrict
seastrict
.
El paso importante es el último: no importa lo que evalúe MemberExpression
, se convierte en un valor de tipo Reference
[espec . ] Este es un tipo de datos que solo se usa en la especificación y contiene información adicional sobre cómo se debe recuperar el valor real de la referencia (¡no se debe confundir con las referencias de objetos en el código JavaScript real!).
Para obtener el valor / resultado "real" de dicha referencia, se llama la función interna GetValue(V)
(§8.7.1) [espec.] (Como en el paso 2 en el algoritmo anterior), donde dice:
GetValue
utiliza el siguiente método interno[[Get]]
cuandoV
es una referencia de propiedad con un valor base primitivo. Se llama usandobase
como su valor y con la propiedadP
como argumento. Se toman los siguientes pasos:
- Sea
O
seaToObject(base)
.
[...]
Ejemplo:
Supongamos que tenemos la expresión
var foo = "BAR".toLowerCase();
Esta es una expresión de asignación que se evalúa de la siguiente manera:
La producción
AssignmentExpression : LeftHandSideExpression = AssignmentExpression
se evalúa de la siguiente manera:
- Sea
lref
el resultado de evaluarLeftHandSideExpression
.- Sea
rref
el resultado de evaluarAssignmentExpression
.- Deje
rval
serGetValue(rref)
.
[...]
Paso 1: Se evalúa el lado izquierdo, que es el identificador foo
. Cómo exactamente se resuelven los identificadores no es importante para esto.
Paso 2: se evalúa el lado derecho, es decir, "BAR".toLowerCase()
. El resultado interno de esa evaluación será un valor de referencia, similar a:
REFERENCE = {
base: "BAR",
propertyNameString: "toLowerCase",
strict: false
}
y almacenados en rref
.
Paso 3: se llama a GetValue(rref)
. La base
de la referencia es el valor "BAR"
. Dado que este es un valor primitivo, se ToObject
a ToObject
para convertirlo en un objeto String
temporal . Además, la referencia es en realidad un acceso de propiedad , por lo que GetValue
eventualmente llamará al método toLowerCase
en el objeto String
y devolverá el resultado del método.
Mientras trabajaba en otro problema, creé este violín:
function foo() {
// console.log(_.isBoolean(this));
console.log(this === true);
}
foo.call(true); // object:[object Boolean]
foo.apply(true); // object:[object Boolean]
¿Es este un ejemplo de auto-boxeo?
Pasando de un tipo de valor a un tipo de referencia.
Aquí hay una definición de wikipedia.
Javascript encaja el argumento que se proporciona para call
y apply
en modo no estricto. Desde MDN :
si el método es una función en código de modo no estricto,
null
eundefined
se reemplazará con el objeto global, y los valores primitivos se encuadrarán.
Las otras respuestas proporcionan información detallada sobre cuándo ocurre el autoboxing, pero aquí hay un par de cosas más para recordar:
Autoboxing no se produce cuando se usa el operador
in
, que lanza unTypeError
si el valor recibido no es un objeto. Una solución simple es encuadrar manualmente el objeto conObject(value)
.Alguna forma de autoboxing ocurre cuando la iteración se usa
for...of
o la sintaxis de propagación[...value]
que permite iterar las cadenas.