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
thisvalor a.callo.apply(.applyno 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ó estethisArgy una lista deargumentsListproporcionados por el llamante:
- Si el código de función es un código estricto, establezca
ThisBindingenthisArg.- De lo contrario, si
thisArgesnulloundefined, establezcaThisBindingen el objeto global.- De lo contrario, si
Type(thisArg)no esObject, establezcaThisBindingenToObject(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
baseReferencesea el resultado de evaluarMemberExpression.- Deje que
baseValueseaGetValue(baseReference).
[...]8. Devuelva un valor de tipo
Referencecuyo valorbaseseabaseValuey cuyo nombre de referencia seapropertyNameStringy cuyo indicador de modostrictseastrict.
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:
GetValueutiliza el siguiente método interno[[Get]]cuandoVes una referencia de propiedad con un valor base primitivo. Se llama usandobasecomo su valor y con la propiedadPcomo argumento. Se toman los siguientes pasos:
- Sea
OseaToObject(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 = AssignmentExpressionse evalúa de la siguiente manera:
- Sea
lrefel resultado de evaluarLeftHandSideExpression.- Sea
rrefel resultado de evaluarAssignmentExpression.- Deje
rvalserGetValue(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,
nulleundefinedse 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 unTypeErrorsi 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...ofo la sintaxis de propagación[...value]que permite iterar las cadenas.