En fait, c'est un problème cliché. Il y a beaucoup d'articles à ce sujet. En fait, je pensais que je l'avais compris, mais hier, j'avais encore un peu de doute pendant le projet. J'ai pensé à un article détaillé que j'avais collecté et lu dans JavaScript Weekly (il y avait un lien plus tard, et la traduction chinoise sur les terres rares a été jointe) et un autre article recommandé par un senior, alors je les ai regardés et ma compréhension de cela s'est en effet un peu amélioré.
«Ceci» en JavaScript est dynamique et est déterminé lorsque la fonction est exécutée, pas lorsque la fonction est déclarée. Toutes les fonctions peuvent appeler «ceci», ce qui n'a pas d'importance si la fonction appartient à un objet. À ce sujet, il existe principalement quatre situations.
1. La méthode utilisée comme objet est appelée
Si la fonction est une méthode qui est considérée comme un objet, alors celle de la fonction pointe vers l'objet;
var John = {premier nom: "John"} fonction func () {alert (this.firstname + ": hi!")} John.sayhi = func John.sayhi () // this = JohnIl y a quelque chose à noter ici. Lorsque la méthode d'un objet est retirée et affectée à une variable, la méthode devient un déclencheur de fonction, et cela pointe vers la fenêtre ou le sous-flux (mode strict).
2. Appelez dans la fonction
Lorsque cette fonction a cela, cela signifie en fait qu'il est appelé comme méthode. L'appel entre les deux équivaut à le traiter comme un objet de fenêtre. Cela pointe vers la fenêtre. Il convient de noter que ES5 stipule en fait que cela = non défini, et seuls les navigateurs sont toujours exécutés selon l'ancienne méthode (je le teste dans la dernière version de Chrome, Safari et Firefox tous pointer vers la fenêtre (201607)), et utiliser le mode strict pour pointer à un non-défini sous Firefox;
func () fonction func () {alert (this) // [fenêtre d'objet] ou [objet global] ou type de ..}Pour passer cela, () devrait être un type de référence avant, similaire à obj.a ou obj ['a'], et ne peut être rien d'autre.
Il y a aussi une petite fosse ici. Lorsqu'il existe une fonction dans la méthode de l'objet, la fonction est en fait déclenchée en mode fonction, donc cette fenêtre par défaut (non définie en mode strict). La solution consiste à lier cela à la fonction.
var nombres = {nombrea: 5, nombreB: 10, sum: function () {console.log (this === nombres); // => true function calcul () {// Ceci est une fenêtre ou non définie en mode strict console.log (this === nombres); // => false return this.numbera + this.numberb; } return calcul (); }}; nombres.sum (); // => nan ou lève TypeError en mode strict nombres var = {nombrea: 5, nombreB: 10, sum: function () {console.log (this === nombres); // => true function calcul () {console.log (this === nombres); // => true return this.numbera + this.numberb; } // Utiliser .Call () Méthode pour modifier le contexte de retour calcul.call (this); }}; nombres.sum (); // => 153. Appelez nouveau
Une variable qui fait référence à un objet enregistre en fait une référence à l'objet, c'est-à-dire que la variable enregistre en fait un pointeur vers les données réelles.
Lorsque vous utilisez le nouveau mot-clé, ce changement prend en fait les étapes suivantes:
Créer ceci = {}.
Cela peut être modifié lors de l'exécution de nouveaux, puis des attributs et des méthodes sont ajoutés;
Renvoie cela a changé.
fonction animal (name) {this.name = name this.canwalk = true} var animal = new animal ("beastie") alert (animal.name)Il convient de noter que si le constructeur renvoie un objet, cela pointe vers l'objet retourné;
fonction animal () {this.name = 'mousie'; this.age = '18'; return {nom: 'godzilla'} // <- sera renvoyé} var animal = new animal () console.log (animal.name) // godzilla console.log (animal.age) // non définiIl est important de noter ici qui n'oublie pas d'utiliser de nouveaux, sinon une nouvelle fonction ne sera pas créée. Au lieu de cela, il exécute simplement la fonction, ce qui équivaut à un appel de fonction, et cela pointe en fait vers la fenêtre
Véhicule de fonction (type, wheelsCount) {this.type = type; this.wheelsCount = wheelsCount; Renvoie ceci;} // fonction invocationvar car = véhicule ('voiture', 4); Type de voiture; // => 'car' car.WheelsCount // => 4 car === fenêtre // => true4. Appelez clairement cela, utilisez l'appel et postulez
C'est l'endroit le plus inspiré du JavaScript.
Le code suivant:
func.call(obj, arg1, arg2,...)
Le premier paramètre sera utilisé comme objet de référence, et le paramètre suivant sera utilisé comme paramètre de la fonction. La solution consiste à utiliser Bind.
fonction animal (type, jambes) {this.type = type; this.legs = jambes; this.loginfo = function () {console.log (this === mycat); // => true console.log ('le' + this.type + 'a' + this.legs + 'jambes'); };} var mycat = nouvel animal ('cat', 4); // Logs "Le chat a 4 jambes" setTimeout (mycat.loginfo.bind (mycat), 1000); // setTimeout ?? var John = {FirstName: "John", incident: "Smith"} fonction func (a, b) {alert (this [a] + '' + this [b])} func.call (John, 'FirstName', 'nom') // "John Smith"Quant à s'appliquer, il passe simplement dans des paramètres dans le carré du tableau, et les autres parties sont les mêmes, comme suit:
func.Call (John, «Firstname», «nom de famille») func.Apply (John, [«Firstname», «nom de famille»]))
Ils peuvent également être utilisés dans l'héritage de la classe dans ES5 pour appeler le constructeur parent.
Function Runner (name) {console.log (cette instance de lapin); // => true this.name = name; } fonction lapin (name, coustregs) {console.log (cette instance de lapin); // => true // Indirectement appelé, The Parent Constructor Runner.Call (this, nom); this.CounTlegs = coustregs; } var myrabbit = nouveau lapin («lapin blanc», 4); myrabbit; // {nom: 'Rabbit blanc', COMPTYGS: 4}5..bind ()
Comparez les méthodes .Apply () et .Call (), qui exécutent tous les deux la fonction immédiatement, tandis que la fonction .bind () renvoie une nouvelle méthode qui lie ce pré-spécifié et peut retarder l'appel.
La fonction de la méthode .bind () est de créer une nouvelle fonction. Le contexte pendant l'exécution est le premier paramètre passé par .bind (), qui permet la création d'une fonction qui a ce préréglage.
var nombres = {array: [3, 5, 10], getNumbers: function () {return this.array; }}; // Créer une fonction BoundVar BoundGetNumbers = nombres.getNumbers.bind (nombres); BoundGetNumbers (); // => [3, 5, 10] // Extrait de la méthode de objectvar simplegetNumbers = nombres.getNumbers; SimpleGetNumbers (); // => non défini ou lance une erreur en mode strictLorsque vous utilisez .bind (), vous devez noter que .bind () crée une chaîne de contexte éternelle et n'est pas modifiable. Même si une fonction de liaison utilise .Call () ou .Apply () pour passer dans d'autres contextes différents, il ne modifiera pas le contexte de sa connexion précédente, et la reliure ne jouera aucun rôle.
Ce n'est que lorsque le constructeur est appelé que la fonction de liaison peut modifier le contexte, mais ce n'est pas une approche particulièrement recommandée.
6. Fonction de flèche
La fonction Arrow ne crée pas le contexte de sa propre exécution, de sorte que cela dépend de la fonction externe qu'elle est définie au moment de la définition.
Les fonctions de flèche ne peuvent pas être modifiées après avoir lié le contexte une fois, même si la méthode de changement de contexte est utilisée:
nombres var = [1, 2]; (fonction () {var get = () => {console.log (this === nombres); // => true return this;}; console.log (this === nombres); // => true get (); // => [1, 2] // functions arrow use .Apply () et .call () get.call ([0]); // => [1, 2] Get.Apply (0])); // => [1, 2] Get.Apply (0])); // => [1, 2] Get.Apply (0]); // => [1, 2] // bind get.bind ([0]) ();En effet, la fonction flèche a un contexte statique et ne changera pas en raison d'appels différents. Par conséquent, n'utilisez pas les fonctions flèches pour définir des méthodes
Période de fonction (heures, minutes) {this.hours = heures; this.minutes = minutes; } Period.prototype.format = () => {console.log (this === fenêtre); // => true return this.hours + 'heures et' + this.minutes + 'minutes'; }; var walkperiod = nouvelle période (2, 30); walkperiod.format (); // => «heures non définies et minutes non définies»se référer à
Quatre parfums de "ceci"
Explication douce de «ce» mot-clé en javascript
Javascript ce mystère (traduction)
Il est fortement recommandé aux étudiants qui ne le comprennent pas. Découvrez les trois articles ci-dessus, le troisième est la traduction du deuxième. Si vous avez des questions à ce sujet, vous êtes invités à discuter ensemble, à communiquer et à promouvoir la réflexion et à progresser ensemble.