Je suis allé pour un entretien avant-hier et un gg m'a posé des questions sur mes connaissances en js. Il y avait une question sur l'utilisation de call and apply. Bien que j'aie utilisé la méthode d'appel il y a 365 jours, je n'ai toujours pas pu y répondre. à ce moment-là, je vais le résumer en profondeur aujourd’hui.
appeler et appliquer, leur fonction est de lier la fonction à un autre objet à exécuter.
Le format et les définitions des paramètres des deux :
call( thisArg [, arg1, arg2, ... ] ); // Liste des paramètres, arg1, arg2, ...
apply(thisArg [, argArray] ); // tableau de paramètres, argArray
Le pointeur this à l'intérieur des deux fonctions ci-dessus se verra attribuer thisArg, ce qui peut réaliser l'objectif d'exécuter la fonction en tant que méthode d'un autre objet.
1. Utilisation simple de l'appel
Tout d’abord, regardons un exemple simple (appel) :
Copiez le code comme suit :
<!doctypehtml>
<html>
<tête>
<title> appel-demande </title>
</tête>
<corps>
<input type="text" id="idTxt" value="input text">
<script type="text/javascript">
valeur var = "var globale" ;
fonction mFunc()
{
this.value = "var membre";
}
fonction gFunc()
{
alert(this.value);
}
window.gFunc();// afficher gFunc, variable globale
gFunc.call(window);// afficher gFunc, variable globale
gFunc.call(new mFunc());// show mFunc, membre var
gFunc.call(document.getElementById('idTxt'));// afficher l'élément, saisir le texte
</script>
<langage de script="javascript">
var func = nouvelle fonction()
{
this.a = "func" ;
}
var func2 = fonction(x)
{
var a = "func2" ;
alert(this.a);
alerte(x);
}
func2.call(func, "func2");// afficher func et func2
</script>
</corps>
</html>
Ensuite, les résultats d'exécution sont les suivants :
variable globalevariable globale
membre var
saisir du texte
fonction
fonction2
Environnement de test : Google Chrome10.0.648.45
Enfin, analysez les résultats
1. L'objet global window appelle la fonction gFunc, et celle-ci pointe vers l'objet window, donc this.value est global var.
2. La fonction gFunc appelle la méthode d'appel. Celle-ci pointe par défaut vers le premier objet de fenêtre de paramètres, donc this.value est également une variable globale.
3. La fonction gFunc appelle la méthode d'appel. La valeur par défaut est le premier paramètre new mFunc(), qui est l'objet de mFunc. Par conséquent, this.value est la variable membre de mFunc.
4. La fonction gFunc appelle la méthode d'appel. Par défaut, celle-ci pointe vers le premier contrôle de texte d'entrée de paramètre, c'est-à-dire le contrôle avec id='idTxt'. Par conséquent, this.value est le texte d'entrée de valeur du contrôle d'entrée.
5. La fonction func2 appelle la méthode d'appel. La valeur par défaut est le premier objet de fonction func de paramètre, donc this.value est this.a, qui est func.
6. La fonction func2 appelle la méthode d'appel. Le deuxième paramètre appartient au paramètre de l'objet fonction func2, donc alert(x) est le deuxième paramètre func2.
2. Utilisation et amélioration de l'héritage d'appel
js utilise un appel pour simuler l'héritage
Code d'essai :
Copiez le code comme suit :
<!doctypehtml>
<html>
<tête>
<title> appel - demande d'héritage </title>
</tête>
<corps>
<script type="text/javascript">
fonction baseA()// base Classe A
{
this.member = "membre baseA";
this.showSelfA = fonction()
{
window.alert(ce.membre);
}
}
fonction baseB()// base Classe B
{
this.member = "membre baseB" ;
this.showSelfB = fonction()
{
window.alert(ce.membre);
}
}
fonction extendAB()//Hériter la classe de A et B
{
baseA.call(this);// appel à A
baseB.call(this);// appel à B
}
window.onload = fonction()
{
var extend = new extendAB();
extend.showSelfA();// afficher A
extend.showSelfB();// afficher B
}
</script>
</corps>
</html>
Les résultats en cours d'exécution sont les suivants :membre baseB
membre baseB
Environnement de test : Google Chrome10.0.648.45
Analyse des résultats :
Le résultat attendu devrait être la sortie du membre baseA et du membre baseB, mais la sortie réelle est le membre baseB et le membre baseB.
(Il a été testé dans IE9, 8, 6, Maxthon, Chrome, FF, Opera, Safari, 360 et d'autres navigateurs, et le résultat est le dernier : membre baseB)
À ce stade, la machine ne s’est pas trompée, ce qui nous oblige à procéder à une analyse approfondie
On peut facilement penser que cela est dû à cela. Cela pointe deux fois vers l'objet baseB, mais est-ce vraiment le cas ?
Afin d'explorer l'essence, nous avons utilisé l'outil de débogage du navigateur Chrome pour définir les points d'arrêt et déboguer, et avons constaté que :
Lorsque extend.showSelfA(); est appelé, cela pointe vers extendAB (et non vers l'objet baseB comme nous l'avons spéculé deux fois)
La vraie raison est que le membre variable membre de l'objet extendAB est écrasé par le membre membre de baseB lorsqu'il est instancié par baseB.call(this) ; c'est-à-dire que le membre membre de extendAB est affecté du membre baseA au membre baseB.
Bien entendu, nous pouvons également modifier légèrement le code baseA ci-dessus pour vérifier l'exactitude de notre analyse de débogage :
Copiez le code comme suit :
fonction baseA()// base Classe A
{
this.memberA = "baseA member" ; // le membre est remplacé par memberA pour distinguer le membre dans baseB
this.showSelfA = fonction()
{
window.alert(this.memberA); // Afficher le membreA
}
}
Exécutez à nouveau des navigateurs tels que Chrome, les résultats sont les suivants :
membre de baseA
membre baseB
Les résultats sont les mêmes que nos attentes, et les informations de débogage de Chrome vérifient également notre exactitude :
Améliorations de l'héritage (prototype)
La méthode d'héritage simulé ci-dessus n'est pas la meilleure après une analyse minutieuse.
Parce que chaque fois qu'une méthode membre est définie dans une fonction (classe), cela entraînera une copie de l'instance, vous pourrez donc utiliser le prototype prototype pour apporter des améliorations.
Des exemples d'améliorations sont les suivants :
Copiez le code comme suit :
<!doctypehtml>
<html>
<tête>
<title> appel - postuler pour un prototype </title>
</tête>
<corps>
<script type="text/javascript">
varClass = {
créer : fonction()// créer une fonction
{
fonction de retour()
{
this.initialize.apply(this, arguments);
}
}
} ;
var Person = Class.create();// Créer une personne de classe
Person.prototype = {// initialisation du prototype
initialiser : fonction (obj1, obj2)
{
ceci.obj1 = obj1 ;
ceci.obj2 = obj2;
},
showSelf : fonction()
{
alert("obj : " + this.obj1 + " et " + this.obj2);
}
}
// Classe d'instance
var person = new Person("man", "women");// deux paramètres
person.showSelf();// afficher la personne
</script>
</corps>
</html>
Les résultats en cours d'exécution sont les suivants :
obj : hommes et femmes