Maison > interface Web > js tutoriel > Conseils, principes de fonctionnement et précautions pour l'utilisation de ce mot-clé dans JavaScript_javascript tips

Conseils, principes de fonctionnement et précautions pour l'utilisation de ce mot-clé dans JavaScript_javascript tips

WBOY
Libérer: 2016-05-16 16:47:30
original
1498 Les gens l'ont consulté

Pour comprendre cela selon sa localisation, la situation peut être grossièrement divisée en trois types :

1. Dans les fonctions : il s'agit généralement d'un paramètre implicite.

2. En dehors de la fonction (dans le périmètre supérieur) : Dans le navigateur, cela fait référence à l'objet global dans Node.js, cela fait référence aux exports du module.

 3. La chaîne passée à eval() : Si eval() est appelé directement, cela fait référence à l'objet courant ; si eval() est appelé indirectement, cela fait référence à l'objet global.

Nous avons effectué des tests correspondants pour ces catégories :
1. ceci dans la fonction

Les fonctions peuvent essentiellement représenter toutes les structures appelables dans JS, c'est donc le scénario le plus courant pour son utilisation, et les fonctions peuvent être divisées en trois rôles suivants :

Fonction réelle
Constructeur
Méthode

 1.1 ceci

en fonctions réelles

Dans les fonctions réelles, la valeur de this est un modèle qui dépend du contexte dans lequel on la trouve.

Mode bâclé : il s'agit de l'objet global (fenêtre du navigateur).

Copier le code Le code est le suivant :

fonction sloppyFunc() {
console .log( this === window); // true
>
sloppyFunc();

Mode strict : la valeur de ceci n'est pas définie.

Copier le code Le code est le suivant :

function strictFunc() {
' utiliser strict' ;
console.log(this === undefined); // true
}
strictFunc();

il s'agit d'un paramètre implicite de la fonction, donc sa valeur est toujours la même. Cependant, vous pouvez définir explicitement la valeur de this en utilisant la méthode call() ou apply().

Copier le code Le code est le suivant :

function func(arg1, arg2) {
console .log(this); // 1
console.log(arg1); // 2
console.log(arg2); // 3
>
func.call(1) , 2, 3); // (this, arg1, arg2)
func.apply(1, [2, 3]); // (this, arrayWithArgs)

1.2 this

dans le constructeur

Vous pouvez utiliser new pour utiliser une fonction comme constructeur. La nouvelle opération crée un nouvel objet et transmet cet objet au constructeur via celui-ci.

Copier le code Le code est le suivant :

var saveThis;
function Constr( ) {
saveThis = this;
}
var inst = new Constr();
console.log(savedThis === inst); // true

Le principe d'implémentation d'une nouvelle opération en JS est à peu près tel qu'indiqué dans le code suivant (veuillez voir ici pour une implémentation plus précise, cette implémentation est également plus compliquée) :

Copier le code Le code est le suivant :

function newOperator(Constr, arrayWithArgs) {
var thisValue = Object.create(Constr.prototype);
Constr.apply(thisValue, arrayWithArgs);
return thisValue;
}

1.3 ceci

dans la méthode

L'utilisation de this dans les méthodes est plus encline aux langages traditionnels orientés objet : le récepteur pointé par this est l'objet qui contient cette méthode.

Copier le code Le code est le suivant :

var obj = {
méthode : function () {
console.log(this === obj); // true
}
>
obj.method();

2. ceci dans le cadre

Dans le navigateur, la portée est la portée globale, et cela fait référence à l'objet global (tout comme la fenêtre) :

Copier le code Le code est le suivant :

<script><br> console. log(this === window); // true<br></script>

Dans Node.js, vous exécutez généralement des fonctions dans des modules. Par conséquent, la portée de niveau supérieur est une portée de module très spéciale :

Copier le code Le code est le suivant :

// `global` (pas `windows `) fait référence à l'objet global :
console.log(Math === global.Math); // true

// `this` ne fait pas référence à l'objet global :
console .log( this !== global); // true
// `this` fait référence aux exportations d'un module :
console.log(this === module.exports); // true

3. ceci dans eval()

eval() peut être appelé directement (en appelant le nom de la fonction 'eval') ou indirectement (appelé par d'autres moyens, comme call()). Pour plus de détails, voir ici.

Copier le code Le code est le suivant :

// Fonctions réelles
fonction sloppyFunc () {
console.log(eval('this') === window); // true
}
sloppyFunc();

function strictFunc() {
'use strict ';
console.log(eval('this') === undefined); // true
>
strictFunc();

// Constructeurs
var saveThis;
function Constr() {
saveThis = eval('this');
>
var inst = new Constr();
console.log(savedThis === inst ); / / true

// Méthodes
var obj = {
méthode : function () {
console.log(eval('this') === obj); / vrai
}
}
obj.method();

4. Pièges liés à cela

Vous devez faire attention aux 3 pièges liés à cela qui seront présentés ci-dessous. A noter que dans les exemples suivants, l'utilisation du mode Strict peut améliorer la sécurité du code. Puisque dans les fonctions réelles, la valeur de this n'est pas définie, vous recevrez un avertissement en cas de problème.

 4.1 J'ai oublié d'utiliser new

Si vous n'utilisez pas new pour appeler le constructeur, alors vous utilisez en fait une vraie fonction. Ce ne sera donc pas la valeur attendue. En mode Sloppy, cela pointe vers la fenêtre et vous créerez des variables globales :

Copier le code Le code est le suivant :

fonction Point(x, y) {
this .x = x;
this.y = y;
}
var p = Point(7, 5); // nous avons oublié new !
console.log(p == = non défini) ; // true

// Des variables globales ont été créées :
console.log(x); // 7
console.log(y);
Cependant, si vous utilisez le mode strict, vous recevrez toujours un avertissement (this===indéfini) :

Copier le code Le code est le suivant :
fonction Point(x, y) {
'use strict';
this.x = x;
this.y = y;
}
var p = Point(7, 5);
// TypeError : Impossible définir la propriété 'x' de non défini

4.2 Mauvaise utilisation des méthodes

Si vous obtenez directement la valeur d'une méthode (sans l'appeler), vous utilisez la méthode comme une fonction. Vous ferez probablement cela lorsque vous souhaitez transmettre une méthode en tant que paramètre dans une fonction ou une méthode appelante. C'est le cas de setTimeout() et des gestionnaires d'événements enregistrés. J'utiliserai la méthode callIt() pour simuler ce scénario :

Copier le code Le code est le suivant :
/**Similaire à setTimeout() et setImmediate()*/
fonction callIt(func) {
func();
}

Si vous appelez une méthode en tant que fonction en mode Sloppy, *this* pointe vers l'objet global, donc toutes les créations ultérieures seront des variables globales.

Copier le code Le code est le suivant :

var counter = {
count: 0,
// Méthode en mode bâclé
inc: function () {
this.count ;
}
}
callIt(counter.inc);

// N'a pas fonctionné :
console.log(counter.count); // 0

// Au lieu de cela, un global la variable a été créée
// (NaN est le résultat de l'application à undefined) :
console.log(count); // NaN

Si vous faites cela en mode Strict, ce n'est pas défini et vous n'obtiendrez toujours pas le résultat souhaité, mais au moins vous recevrez un avertissement :

Copier le code Le code est le suivant :

var counter = {
count : 0,
// Méthode en mode strict
inc: function () {
'use strict';
this.count ;
}
>
callIt(counter. inc);

// TypeError : Impossible de lire la propriété 'count' de undefined
console.log(counter.count);

Pour obtenir les résultats attendus, vous pouvez utiliser bind() :

Copier le code Le code est le suivant :

var counter = {
count : 0,
inc: function () {
this.count ;
}
>
callIt(counter.inc.bind(counter));
// Ça a marché !
console .log(counter.count); // 1

bind() crée une autre fonction qui définit toujours la valeur de this sur counter.

 4.3 Cacher ceci

Quand on utilise une fonction dans une méthode, on oublie souvent que la fonction a son propre this. Ceci est différent des méthodes, vous ne pouvez donc pas mélanger les deux. Pour plus de détails, veuillez consulter le code suivant :

Copier le code Le code est le suivant :

var obj = {
nom : 'Jane' ,
amis : [ 'Tarzan', 'Cheeta' ],
loop: function () {
'use strict';
this.friends.forEach(
function ( ami) {
            console.log(this.name ' sait ' ami);
                              ; Impossible de lire la propriété 'nom' de non défini



Dans l'exemple ci-dessus, this.name dans la fonction ne peut pas être utilisé car la valeur de this dans la fonction n'est pas définie, ce qui est différent de celle de la méthode loop(). Trois idées sont proposées ci-dessous pour résoudre ce problème :

1. that=this, attribuez ceci à une variable, afin que cela soit explicitement affiché (en plus de cela, self est également un nom de variable très courant utilisé pour stocker ceci), puis utilisez cette variable :

Copier le code

Le code est le suivant :boucle : fonction() { 'use strict '; var that = this;
this.friends.forEach(function (friend) {
console.log(that.name 'knows'friend);
});
}



2. lier(). Utilisez bind() pour créer une fonction dont this contient toujours la valeur que vous souhaitez transmettre (dans l'exemple ci-dessous, le this de la méthode) :

Copier le code

Le code est le suivant :boucle : fonction() { 'use strict '; this.friends.forEach(function (friend) {
console.log(this.name ' sait ' ami);
}.bind(this));
}

3. Utilisez le deuxième paramètre de forEach. Le deuxième paramètre de forEach sera transmis à la fonction de rappel et utilisé comme celui-ci de la fonction de rappel.

Copier le codeLe code est le suivant :

boucle : fonction() {
'use strict ';
this.friends.forEach(function (friend) {
console.log(this.name 'knows'friend);
}, this);
}

5. Bonnes pratiques

Théoriquement, je pense que les fonctions réelles n'ont pas leur propre ceci, et la solution ci-dessus est également basée sur cette idée. ECMAScript 6 utilise des fonctions fléchées pour obtenir cet effet. Les fonctions fléchées sont des fonctions qui n'ont pas leur propre this. Dans une telle fonction, vous pouvez l'utiliser avec désinvolture et vous n'avez pas à vous soucier de son existence implicite.

Copier le codeLe code est le suivant :

boucle : fonction() {
'use strict ';
// Le paramètre de forEach() est une fonction fléchée
this.friends.forEach(friend => {
// `this` est le `this`
de la boucle console.log (ce.nom 'connaît' ami);
});
}

Je n'aime pas que certaines API traitent cela comme un paramètre supplémentaire de la fonction réelle :

Copier le code Le code est le suivant :

beforeEach(function () {
this.addMatchers ({
toBeInRange : function (début, fin) {
...
} }
});

Écrivez un paramètre implicite comme explicite et transmettez-le, le code sera plus facile à comprendre, et cela est cohérent avec les exigences de la fonction flèche :

Copier le code Le code est le suivant :
beforeEach(api => {
api. addMatchers({
             toBeInRange(start, end) {                                                                                              
Étiquettes associées:
source:php.cn
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal