Introdução
1. Tipo de referência
O tipo de referência é um tipo interno em JavaScript. É usado principalmente como referência, substituindo uma variável ou função. Claro, quando o valor real é necessário, o valor real pode ser encontrado através dele.
2. Estrutura do tipo de referência
O valor de um tipo de referência consiste em duas partes. Uma é o objeto ao qual pertence o objeto referido pelo valor do tipo de referência. Aqui o chamamos de base, e a outra é o nome do objeto referido em base. . Representado em pseudocódigo:
Copie o código do código da seguinte forma:
var valorOfReferenceType = {
base: <objeto base>,
nomedapropriedade: <nome da propriedade>
};
3. Cenários de uso
Existem dois cenários de uso para tipos de referência:
(1) Ao processar um identificador
Identificadores são nomes de variáveis, nomes de funções, nomes de parâmetros de funções e nomes de propriedades não reconhecidos em objetos globais.
(2) Ao processar um acessador de propriedade
Copie o código do código da seguinte forma:
var foo = 10;
barra de funções( ){}
Nos resultados intermediários da operação, o tipo de referência corresponde a
Copie o código do código da seguinte forma:
var fooReferência = {
base: global,
nome da propriedade: 'foo'
};
var referênciabarra = {
base: global,
nomedapropriedade: 'barra'
};
Ainda é necessário explicar a base aqui. Em JavaScript, todos os objetos ou funções possuem seus próprios objetos. Quem leu meu artigo anterior sabe que existe um objeto variável em cada contexto de execução para gerenciar as variáveis ou funções neste contexto de execução. .
Então, ao lidar com identificadores:
No contexto global, nem é preciso dizer que base === globalVO === global
No contexto de execução da função, base === VO/AO
Mas as propriedades do objeto de processamento são:
Isso é ainda mais simples, base === owerObject
4. Obtenha o valor verdadeiro do tipo de referência
Como dissemos no início, um tipo de referência é apenas uma referência, mas não armazena o valor real. Quando o valor real é necessário, ele pode ser obtido através de uma série de algoritmos internos. Podemos descrever este algoritmo com pseudocódigo simples:
Copie o código do código da seguinte forma:
function GetValue(valor) {
if (Tipo(valor) != Referência) {
valor de retorno;
}
var base = GetBase(valor);
if (base === nulo) {
lançar novo ReferenceError;
}
return base.[[Get]](GetPropertyName(valor));
}
O método interno [[Get]] retorna o valor verdadeiro das propriedades do objeto, incluindo a análise das propriedades herdadas na cadeia de protótipos. Assim, através de GetValue também podemos obter facilmente o valor real do tipo de referência. Por exemplo:
Copie o código do código da seguinte forma:
GetValue(fooReferência); // 10
GetValue(barReference); // objeto de função "bar"
Então, quando precisamos obter o valor real do tipo de referência?
Geralmente, quando um tipo de referência precisa ser atribuído, participar de uma operação ou ser chamado, o valor real precisa ser obtido através do método GetValue. (Nota: O objeto obtido através de GetValue não é mais um tipo de referência)
A relação entre os tipos de referência e este
O tipo de referência está intimamente relacionado ao ponto this no contexto da função e parece bastante diferente em momentos diferentes, portanto, introduzimos o tipo de referência para explicar especificamente o desempenho this no contexto da função.
As regras gerais para determinar o valor disto no contexto da função são as seguintes:
No contexto de uma função, isso é fornecido pelo chamador e é determinado pela forma como a função é chamada. Se o lado esquerdo do colchete de chamada () for um valor do tipo de referência, este será definido como o objeto base do valor do tipo de referência. Em outros casos (quaisquer outras propriedades diferentes do tipo de referência), este valor será nulo. . Porém, não existe uma situação real em que o valor de this seja nulo, pois quando o valor de this for nulo, seu valor será convertido implicitamente em um objeto global. Nota: Na quinta edição do ECMAScript, a conversão para variáveis globais não é mais forçada, mas é atribuída a indefinidas.
Abaixo discutiremos três situações com base na diferença no lado esquerdo do colchete de chamada:
(1) O lado esquerdo do colchete de chamada é o valor do tipo de referência
Isso não requer muita análise. O objeto base é o valor disso. Se for declarado sob uma variável global, aponta para o objeto global.
Copie o código do código da seguinte forma:
var meuObjeto = {
foo: função(){
console.log(isto);
}
}
myObject.foo(); //Não há dúvida de que a base de foo é myObject, então isso no método foo aponta para myObject.
(2) O lado esquerdo do colchete de chamada é um valor do tipo de referência, mas esse valor é nulo
Copie o código do código da seguinte forma:
function minhaFunção() {
var foo = função(){
console.log(este);
}
foo(); //AO.foo() => null.foo();
}
myFunction(); //Saída: Janela {parte superior: Janela, janela: Janela...}
Quando uma função interna é chamada, a base da função interna deve ser o objeto ativo (OA) no contexto de execução atual. No entanto, dentro do JavaScript, quando o OA é usado como base, ele é tratado como nulo. permitir que this seja null , toda a base é definida para o objeto global (esta é a fonte do erro de design no padrão de chamada de função anterior). Portanto, neste caso, this aponta para o objeto global.
(3) Chame o valor no lado esquerdo do colchete que não é um tipo de referência
Copie o código do código da seguinte forma:
//Exemplo simples
(função () {
console.log(this); // null => global
})();
//Um exemplo mais complexo
var foo = {
barra: função () {
console.log(este);
}
};
foo.bar(); // Referência, OK => foo
(foo.bar)(); // Referência, OK => foo
(foo.bar = foo.bar)();
(falso || foo.bar)();
(foo.bar, foo.bar)();
Quando o lado esquerdo do colchete de chamada não é um tipo de referência, mas outro tipo, isso é automaticamente definido como nulo e o resultado é o objeto global.
No primeiro exemplo, a função imediata possui uma expressão no lado esquerdo do parêntese de chamada de função, não uma referência.
O segundo exemplo é bem mais complicado, vamos analisar um por um:
foo.bar(), não há dúvida sobre isso, base é foo e isso aponta para foo.
(foo.bar)(), aqui é utilizado um parêntese, que atua como um símbolo de agrupamento, ou seja, não força o tipo de referência a executar o método GetValue, e o resultado da execução é exatamente igual ao anterior.
Os próximos três, entre parênteses, são operações de atribuição, ou operações e operações de vírgula. Todas elas forçam o tipo de referência a executar o método GetValue, retornando assim um objeto de função. Desta forma, o lado esquerdo dos parênteses da chamada de função não é mais um tipo de referência, portanto aponta para o objeto global.
Resumir
Em relação aos tipos de referência, na verdade não sei muito sobre isso, acabei de ver o capítulo sobre isso no blog do Tio Tom. Para explicar o princípio do valor disso no modo de chamada de função, fiz uma análise especial. incrível. Sempre pensei que deveria haver alguma relação entre tipos de referência e referência por valor. Inesperadamente, é usado apenas no bolg para auxiliar na compreensão disso. Quanto a saber se existia uma relação entre os dois antes, e se existia uma relação, que tipo de relação era, ainda preciso continuar estudando e pesquisando.
Espero que você possa se comunicar mais. Gostaria de agradecer ao Tio Tom por isso.