Introducción
1. Tipo de referencia
El tipo de referencia es un tipo interno en JavaScript. Se utiliza principalmente como referencia, reemplazando una variable o función. Por supuesto, cuando se necesita el valor real, el valor real se puede encontrar a través de él.
2. Estructura del tipo de referencia.
El valor de un tipo de referencia consta de dos partes: una es el objeto al que pertenece el objeto al que hace referencia el valor del tipo de referencia, aquí lo llamamos base, y la otra es el nombre del objeto al que hace referencia la base. . Representado en pseudocódigo:
Copie el código de código de la siguiente manera:
var valorDeTipoReferencia = {
base: <objeto base>,
nombre de propiedad: <nombre de propiedad>
};
3.Escenarios de uso
Hay dos escenarios de uso para los tipos de referencia:
(1) Al procesar un identificador
Los identificadores son nombres de variables, nombres de funciones, nombres de parámetros de funciones y nombres de propiedades no reconocidas en objetos globales.
(2) Al procesar un acceso a la propiedad
Copie el código de código de la siguiente manera:
varfoo = 10;
barra de funciones( ){}
En los resultados intermedios de la operación, el tipo de referencia corresponde a
Copie el código de código de la siguiente manera:
var fooReferencia = {
base: mundial,
Nombre de propiedad: 'foo'
};
var referenciabarra = {
base: mundial,
Nombre de propiedad: 'barra'
};
Todavía es necesario explicar la base aquí. En JavaScript, todos los objetos o funciones tienen sus propios objetos. Cualquiera que haya leído mi artículo anterior sabe que hay un objeto variable en cada contexto de ejecución para administrar las variables o funciones en este contexto de ejecución. .
Entonces, cuando se trata de identificadores:
En el contexto global, no hace falta decir que base === globalVO === gloabal
En el contexto de ejecución de la función, base === VO/AO
Pero las propiedades del objeto de procesamiento son:
Esto es aún más simple, base === powerObject
4. Obtenga el valor real del tipo de referencia.
Como dijimos al principio, un tipo de referencia es solo una referencia, pero no almacena el valor real. Cuando se necesita el valor real, se puede obtener mediante una serie de algoritmos internos. Podemos describir este algoritmo con un pseudocódigo simple:
Copie el código de código de la siguiente manera:
función ObtenerValor(valor) {
if (Tipo(valor) != Referencia) {
valor de retorno;
}
var base = GetBase(valor);
si (base === nulo) {
lanzar un nuevo error de referencia;
}
base de retorno.[[Get]](GetPropertyName(valor));
}
El método interno [[Get]] devuelve el valor verdadero de las propiedades del objeto, incluido el análisis de las propiedades heredadas en la cadena del prototipo. Entonces, a través de GetValue también podemos obtener fácilmente el valor real del tipo de referencia. Por ejemplo:
Copie el código de código de la siguiente manera:
GetValue(fooReferencia); // 10
GetValue(barReference); // objeto de función "barra"
Entonces, ¿cuándo necesitamos obtener el valor real del tipo de referencia?
Generalmente, cuando es necesario asignar un tipo de referencia, participar en una operación o llamarlo, el valor real debe obtenerse mediante el método GetValue. (Nota: el objeto obtenido a través de GetValue ya no es un tipo de referencia)
La relación entre los tipos de referencia y esto.
El tipo de referencia está estrechamente relacionado con este punto en el contexto de la función y se ve bastante diferente en diferentes momentos, por lo que introducimos el tipo de referencia para explicar específicamente el desempeño de esto en el contexto de la función.
Las reglas generales para determinar el valor de this en el contexto de la función son las siguientes:
En el contexto de una función, esto lo proporciona la persona que llama y está determinado por cómo se llama la función. Si el lado izquierdo del corchete de llamada () es un valor de tipo de referencia, este se establecerá en el objeto base del valor del tipo de referencia. En otros casos (cualquier otra propiedad diferente del tipo de referencia), este valor será nulo. . Sin embargo, no existe una situación real en la que el valor de this sea nulo, porque cuando el valor de this es nulo, su valor se convertirá implícitamente en un objeto global. Nota: En la quinta edición de ECMAScript, la conversión a variables globales ya no se fuerza, sino que se asigna a indefinida.
A continuación analizaremos tres situaciones basadas en la diferencia en el lado izquierdo del grupo de llamadas:
(1) El lado izquierdo del paréntesis de llamada es el valor del tipo de referencia
Esto no requiere demasiado análisis. El objeto base es el valor de esto. Si se declara bajo una variable global, apunta al objeto global.
Copie el código de código de la siguiente manera:
var miObjeto = {
foo: función(){
consola.log(esto);
}
}
myObject.foo(); //No hay duda de que la base de foo es myObject, por lo que esto en el método foo apunta a myObject.
(2) El lado izquierdo del paréntesis de llamada es un valor de tipo de referencia, pero este valor es nulo
Copie el código de código de la siguiente manera:
función miFunción() {
var foo = función(){
consola.log(esto);
}
foo(); //AO.foo() => nulo.foo()
}
myFunction(); //Salida: Ventana {arriba: Ventana, ventana: Ventana...}
Cuando se llama a una función interna, la base de la función interna debe ser el objeto activo (OA) en el contexto de ejecución actual. Sin embargo, dentro de JavaScript, cuando se utiliza OA como base, JavaScript ciertamente no lo trata como nulo. permita que esto sea nulo, toda la base se establece en el objeto global (esta es la fuente del error de diseño en el patrón de llamada de esta función anterior). Entonces, en este caso, esto apunta al objeto global.
(3) Llame al valor en el lado izquierdo del paréntesis que no es un tipo de referencia
Copie el código de código de la siguiente manera:
//Ejemplo sencillo
(función () {
console.log(esto); // nulo => global
})();
//Un ejemplo más complejo
varfoo = {
barra: función () {
consola.log(esto);
}
};
foo.bar(); // Referencia, OK => foo
(foo.bar)(); // Referencia, OK => foo
(foo.bar = foo.bar)(); // global
(falso || foo.bar)(); // global
(foo.bar, foo.bar)();
Cuando el lado izquierdo del paréntesis de llamada no es un tipo de referencia sino otro tipo, esto se establece automáticamente en nulo y el resultado es el objeto global.
En el primer ejemplo, la función inmediata tiene una expresión en el lado izquierdo del paréntesis de la llamada a la función, no una referencia.
El segundo ejemplo es mucho más complicado, analicémoslo uno por uno:
foo.bar(), de esto no hay duda, la base es foo y esto apunta a foo.
(foo.bar) (), aquí se usa un paréntesis, que actúa como un símbolo de agrupación, es decir, no fuerza al tipo de referencia a ejecutar el método GetValue, y el resultado de la ejecución es exactamente el mismo que el anterior.
Las tres siguientes, entre paréntesis, son operaciones de asignación u operaciones y operaciones de coma. Todas obligan al tipo de referencia a ejecutar el método GetValue, devolviendo así un objeto de función. De esta manera, el lado izquierdo del paréntesis de la llamada a la función ya no es un tipo de referencia, por lo que apunta al objeto global.
Resumir
Con respecto a los tipos de referencia, en realidad no sé mucho sobre esto. Acabo de ver el capítulo sobre esto en el blog del tío Tom. Para explicar el principio de valor de esto en el modo de llamada de función, hice un análisis especial. Increíble. Siempre he pensado que debería haber alguna relación entre los tipos de referencia y la referencia por valor. Inesperadamente, solo se usa en bolg para ayudar a comprender esto. En cuanto a si había una relación entre los dos antes, y si había una relación, qué tipo de relación era, todavía necesito seguir estudiando e investigando.
Espero que puedas comunicarte más. Me gustaría agradecer al tío Tom por esto.