Fui para uma entrevista anteontem e um gg me perguntou sobre alguns conhecimentos de js. Havia uma dúvida sobre o uso de call and apply Embora eu tivesse usado o método call 365 dias atrás, ainda não consegui responder. naquela época. Vou resumi-lo em profundidade hoje.
chamar e aplicar, sua função é vincular a função a outro objeto para execução.
As definições de formato e parâmetro de ambos:
call( thisArg [, arg1, arg2, ... ] ); // Lista de parâmetros, arg1, arg2, ...
apply(thisArg [, argArray] ); // array de parâmetros, argArray
O ponteiro this dentro das duas funções acima receberá thisArg, que pode realizar o propósito de executar a função como um método de outro objeto.
1. Uso simples de chamada
Primeiro, vejamos um exemplo simples (chamada):
Copie o código do código da seguinte forma:
<!doctypehtml>
<html>
<cabeça>
<title> chamada-aplicação </title>
</head>
<corpo>
<input type="text" id="idTxt" value="input text">
<script type="texto/javascript">
var valor = "var global";
função mFunc()
{
this.value = "membro var";
}
função gFunc()
{
alerta(este.valor);
}
window.gFunc(); // mostra gFunc, var global
gFunc.call(janela); // mostra gFunc, var global
gFunc.call(new mFunc()); // mostra mFunc, membro var
gFunc.call(document.getElementById('idTxt'));// mostra elemento, texto de entrada
</script>
<linguagem script="javascript">
var função = nova função()
{
isto.a = "func";
}
var func2 = função(x)
{
var a = "func2";
alerta(este.a);
alerta(x);
}
func2.call(func, "func2"); // mostra func e func2
</script>
</body>
</html>
Então, os resultados da execução são os seguintes:
variável globalvariável global
membro var
texto de entrada
função
função2
Ambiente de teste: Google Chrome10.0.648.45
Por fim, analise os resultados
1. O objeto global window chama a função gFunc, e isso aponta para o objeto window, então this.value é var global.
2. A função gFunc chama o método call This aponta para o primeiro objeto de janela de parâmetro por padrão, então this.value também é uma var global.
3. A função gFunc chama o método de chamada. O padrão é o primeiro parâmetro new mFunc(), que é o objeto de mFunc. Portanto, this.value é a variável membro de mFunc.
4. A função gFunc chama o método call. Por padrão, isso aponta para o primeiro controle de texto de entrada de parâmetro, ou seja, o controle com id='idTxt'. Portanto, this.value é o texto de entrada do valor do controle de entrada.
5. A função func2 chama o método de chamada. O padrão é o primeiro parâmetro do objeto de função func, então this.value é this.a, que é func.
6. A função func2 chama o método de chamada. O segundo parâmetro pertence ao parâmetro do objeto de função func2, então alert(x) é o segundo parâmetro func2.
2. Uso e melhoria de herança de chamadas
js usa chamada para simular herança
Código de teste:
Copie o código do código da seguinte forma:
<!doctypehtml>
<html>
<cabeça>
<title> chamada - solicitar herança </title>
</head>
<corpo>
<script type="texto/javascript">
função baseA() // base Classe A
{
this.member = "membro baseA";
this.showSelfA = função()
{
janela.alert(este.membro);
}
}
função baseB() // base Classe B
{
this.member = "membro baseB";
this.showSelfB = função()
{
janela.alert(este.membro);
}
}
function extendAB() // Herda classe de A e B
{
baseA.call(this);// chamada para A
baseB.call(this);// chamada para B
}
janela.onload=função()
{
var estender = new estenderAB();
extend.showSelfA(); // mostra A
extend.showSelfB(); // mostra B
}
</script>
</body>
</html>
Os resultados da execução são os seguintes:membro baseB
membro baseB
Ambiente de teste: Google Chrome10.0.648.45
Análise de resultados:
O resultado esperado deve ser a saída de membro baseA e membro baseB, mas a saída real é membro baseB e membro baseB.
(Foi testado em IE9, 8, 6, Maxthon, Chrome, FF, Opera, Safari, 360 e outros navegadores, e o resultado é o último: membro baseB)
Neste ponto, a máquina não está errada, o que exige que façamos uma análise aprofundada
Podemos facilmente pensar que isso é causado por isso. This aponta para o objeto baseB duas vezes, mas será realmente esse o caso?
Para explorar a essência, usamos a ferramenta de depuração do navegador Chrome para definir pontos de interrupção e depuração e descobrimos que:
Quando extend.showSelfA() é chamado, aponta para extendAB (não para o objeto baseB como especulamos duas vezes)
A verdadeira razão é que a variável de membro member do objeto extendAB é substituída pelo membro membro de baseB quando é instanciado por baseB.call(this);, ou seja, o membro membro de extendAB é atribuído do membro baseA ao membro baseB.
Claro, também podemos modificar ligeiramente o código baseA acima para verificar a exatidão de nossa análise de depuração:
Copie o código do código da seguinte forma:
função baseA() // base Classe A
{
this.memberA = "membro baseA" // membro é alterado para membroA para distinguir o membro em baseB;
this.showSelfA = função()
{
window.alert(this.memberA); // Exibir membroA;
}
}
Execute navegadores como o Chrome novamente, os resultados são os seguintes:
membro baseA
membro baseB
Os resultados são iguais às nossas expectativas, e as informações de depuração do Chrome também verificam nossa correção:
Melhorias de herança (protótipo)
O método de herança simulada acima não é o melhor após uma análise cuidadosa.
Porque toda vez que um método membro é definido em uma função (classe), ele causará uma cópia da instância, então você pode usar o protótipo do protótipo para fazer melhorias.
Exemplos de melhorias são os seguintes:
Copie o código do código da seguinte forma:
<!doctypehtml>
<html>
<cabeça>
chamada <title> - solicite protótipo </title>
</head>
<corpo>
<script type="texto/javascript">
varClass = {
criar: função() // criar função
{
função de retorno()
{
this.initialize.apply(isto, argumentos);
}
}
};
var Pessoa = Class.create();// Cria Pessoa da Classe
Person.prototype = {// inicialização do protótipo
inicializar: função (obj1, obj2)
{
isto.obj1 = obj1;
isto.obj2 = obj2;
},
mostrarSelf: função()
{
alert("obj: " + this.obj1 + " e " + this.obj2);
}
}
//instância Classe
var pessoa = new Person("homem", "mulheres"); // dois parâmetros
person.showSelf();//mostra pessoa
</script>
</body>
</html>
Os resultados da execução são os seguintes:
obj: homens e mulheres