Maison  >  Article  >  interface Web  >  Explication détaillée de ce mot-clé en javascript

Explication détaillée de ce mot-clé en javascript

巴扎黑
巴扎黑original
2016-12-22 13:37:481025parcourir

Peu importe les connaissances que nous apprenons, s'habituer à dresser une liste des connaissances que nous avons acquises nous aidera à clarifier notre réflexion et constitue une bonne méthode d'apprentissage. Fortement recommandé.

Ce qui suit est un peu long, j'espère donc que les lecteurs le liront patiemment.

Le contenu suivant sera divisé en parties suivantes :

1. Signification

 1.1 : La signification de ceci

 1.2 : La variabilité de ceci point

2. Occasions d'utilisation

2.1 : Environnement global

2.2 : Constructeur

2.3 : Méthodes objets

3. Notes sur utilisez

 3.1 : Évitez l'imbrication à plusieurs niveaux de ceci

 3.2 : Évitez ceci

dans les méthodes de traitement de tableau 3.3 : Évitez cela

dans les fonctions de rappel 1 . Signification

1.1 : La signification de ceci

Comme mentionné dans un article de blog que j'ai écrit sur la relation entre le constructeur et le nouveau mot-clé, le nouveau mot-clé renvoie toujours un objet. Cet objet peut être l'objet vide renvoyé lorsque new appelle le constructeur, ou il peut s'agir d'un type de données complexe (incluant des objets, des tableaux, etc.) renvoyé à l'aide de l'instruction return dans le constructeur.

De même, comme le mot-clé new, le mot-clé this renvoie toujours un objet. Pour être plus précis, il s’agit de l’objet où réside « actuellement » la propriété ou la méthode.

var Keith = {
  firstName: 'Chou',
  describe: function() {
   return this.firstName;
  }
 };
console.log(Keith.describe()); //'Chou'

Dans le code ci-dessus, this.firstName représente l'attribut firstName de l'objet où se trouve actuellement la méthode de description. En d'autres termes, lorsque la méthode de description est appelée dans la portée globale, l'objet actuel où se trouve la méthode de description est Keith, donc Keith.firstName est appelé.

1.2 : Variabilité pointée par ceci

Étant donné que les propriétés d'un objet peuvent être attribuées à un autre objet, l'objet actuel où se trouvent les propriétés est variable. En d’autres termes, le pointeur de ceci est variable.

var Keith = {
  firstName: 'Chou',
  describe: function() {
   return this.firstName;
  }
 };
 var Rascal={
  firstName: 'King'
 }
 Rascal.describe=Keith.describe;
 console.log(Rascal.describe()); //'King'

Dans le code ci-dessus, l'attribut décrire dans l'objet Keith est attribué à Rascal, donc l'objet actuel dans la méthode décrire est Rascal, donc this.firstName pointe vers Rascal . Parce qu'il est transmis par adresse, la modification de firstName aura un impact sur l'objet d'origine. Cet exemple n'est peut-être pas facile à comprendre, alors jetez un œil à l'exemple suivant.

function f(){
  return this.firstName;
 }
 var Keith = {
  firstName: 'Chou',
  describe:f
 };
 var Rascal={
  firstName: 'King',
  describe:f
 }
 console.log(Keith.describe()); //'Chou'
 console.log(Rascal.describe()); //'King'

Dans le code ci-dessus, la méthode est déplacée vers la portée globale et le mot-clé this est utilisé dans la fonction f. Comme l’objet où se trouve f est différent, cela pointe vers des objets différents.

Dans la portée globale, le mot-clé this pointera vers l'objet de niveau supérieur (c'est-à-dire l'objet window).

var name='keith';
 function person(){
  var name='rascal';
  return this.name;
 }
console.log(person()); //'keith'

Dans le code ci-dessus, Keith est renvoyé à la place de rascal. La raison est que cela indique une portée mondiale. La définition d'une fonction dans la portée globale pointe vers l'objet window par défaut, pas vers la fonction elle-même. Cependant, si vous n'utilisez pas var pour déclarer une variable locale dans la fonction, les résultats seront différents.

var name='keith';
 function person(){
  name='rascal';
  return this.name;
 }
console.log(person()); //'rascal'

Dans le code ci-dessus, var n'est pas utilisé pour déclarer une variable locale à l'intérieur de la fonction, donc l'attribut name à l'intérieur de la fonction à ce moment n'est pas une variable locale, mais une variable globale. Par conséquent, l’attribut de nom précédent sera écrasé. Si vous ne connaissez pas les variables locales et les variables globales, vous pouvez visiter cet article.

Tant que la fonction est affectée à une autre variable, le pointeur de celle-ci changera.

var Keith={
  name:'keith',
  describe:function(){
   return this.name;
  }
 }
var name='rascal';
var f=Keith.describe;
console.log(f()) //'rascal'

Dans le code ci-dessus, c'est Rascal qui est renvoyé, pas Keith. Étant donné que Keith.describe est affecté à la variable f et qu'il existe une variable name dans la portée globale, le pointeur this de la fonction à l'intérieur de Keith pointera vers l'objet sur lequel f s'exécute (l'objet de niveau supérieur, c'est-à-dire le window object)

Pour résumer :

1 Dans le langage JavaScript, tout est un objet (sauf indéfini et nul), et l'environnement d'exécution est également un objet, donc les fonctions s'exécutent dans un certain objet, et c'est cet objet (environnement).

2.Le pointage de ceci est dynamique. Si la fonction est dans la portée globale, alors cela pointera vers l'environnement global ; si la fonction est dans un objet, alors cela pointera vers l'objet.

2. Occasions d'utilisation

Les occasions d'utilisation de ceci peuvent être divisées en occasions suivantes.

2.1 : Environnement global (portée globale)

Utilisez cet objet dans la portée globale, qui pointe vers l'objet de niveau supérieur, qui est l'objet fenêtre.

function keith() {
  return (this === window)
  }
console.log(keith()) //true

Dans le code ci-dessus, qu'il se trouve ou non à l'intérieur d'une fonction, tant qu'il est exécuté dans la portée globale, cela pointe vers la fenêtre d'objet de niveau supérieur.

2.2 : Constructeur

Ceci dans le constructeur pointe vers l'instance d'objet à créer.

function Keith() {
  this.sex = 'boy';
 }
 var person = new Keith();
 console.log(person.sex); //'boy'

Dans le code ci-dessus, le constructeur Keith est défini dans la portée globale, puis le constructeur est appelé et affecté à l'instance d'objet personne.

Il y a trois exigences de base pour la création d'un constructeur : la première lettre du nom de la fonction est en majuscule ; le mot-clé this est utilisé à l'intérieur du constructeur pour pointer vers l'instance d'objet à générer ; le mot-clé new est utilisé pour appeler ; le constructeur et renvoie l’instance d’objet.

Si vous souhaitez en savoir plus sur la relation entre le constructeur et le nouveau mot-clé, veuillez consulter cet article.

2.3 : Méthodes d'objet

Lorsqu'une méthode de l'objet A est assignée à l'objet B, celle-ci dans la méthode passe du pointage vers l'objet A au pointage vers l'objet B. Soyez donc particulièrement prudent lors de l'affectation d'une méthode d'un objet à un autre objet, le pointeur de celui-ci sera modifié.

var keith = {
  sex: 'boy',
  foo: function() {
   return this.sex;
  }
 };
 var rascal = {
  sex: 'girl'
 };
 rascal.foo = keith.foo;
 console.log(keith.foo()); //'boy'
 console.log(rascal.foo()); //'girl'

Dans le code ci-dessus, la fonction foo de Keith est attribuée à rascal, puis le but de cela passe de Keith à rascal.

如果某个方法位于多层对象的内部,这时为了简化书写,把该方法赋值给一个变量,往往会得到不一样的结果。

var a = {
  b: {
   p: 'keith',
   c: function() {
    return this.p;
   }
  }
 };
 var person = a.b.c;
 console.log(person()); //undefined

上面代码中,c是两层对象里面的一个方法。为求简便,将其赋值给全局变量person,结果调用时,this指向了顶层对象window。而在window中变量p默认值为undefined。

要解决这个问题,可以只将c所在的对象赋值给person变量,或者是直接调用。

var person = a.b;
console.log(person.c()); //'keith'
console.log(a.b.c()); //'keith'

3.使用注意点

3.1:避免多层嵌套this

当在闭包中使用多层this,则this都会指向window。

function keith() {
  console.log(this);
  return function() {
   return this;
  }
 }
 keith(); //window
 keith()(); //window

上面代码中,在一个函数中返回另外一个匿名函数是闭包的特点之一,可以看出,当在闭包中使用this对象都会指向全局作用域中的window对象。

如果在函数外包含一个对象,则内部this指向全局作用域,而外部this对象指向当前作用域。

var o = {
  f1: function() {
   console.log(this);
   (function() {
    console.log(this)
   })();
  }
 };
 o.f1(); //Object , Window

   

上面代码包含两层this,结果运行后,第一层指向当前对象,第二层指向全局对象。

实际执行的是如下代码。

function keith() {
  console.log(this);
 }
 var o = {
  f1: function() {
   console.log(this);
   var f2 = keith();
  }
 };
 o.f1(); //Object , Window

要实现多层this嵌套,有两种解决方法:

一是在第二层中改用一个指向外层this的变量。

var o = {
  f1: function() {
   console.log(this);
   var that = this;
   (function() {
    console.log(that);
   })();
  }
 };
 o.f1(); //Object , Object

上面代码中,定义了局部变量that,固定指向了外层的this,然后在内层中使用that,就不会发生this指向的改变。但是如果函数外部内有嵌套一个对象,this还是会指向全局。

二是Javascript中的严格模式。在严格模式下,如果内部函数的this指向了window对象,就会报错。

var a = {
  count: 0,
  fun: function() {
   'use strict';
   return this.count++;
  }
 }
 var f = a.fun;
 console.log(f()) //'TypeError: this is undefined'

上面代码中,fun方法使用严格模式声明。把a对象中的fun方法赋值给全局变量f,那么this此时指向window对象,在严格模式下,就会报错。如果函数外部没有嵌套一个对象,那么不会报错,而是会返回undefined。

3.2:避免数组处理方法中的this

  数组的map和foreach方法,允许提供一个函数作为参数。这个函数内部不应该使用this。

var keith = {
  a: 'Hello',
  b: ['b1', 'b2'],
  c: function() {
   this.b.forEach(function(item) {
    console.log(this.a + ' ' + item);
   })
  }
 };
 keith.c();
 //undefined b1
 //undefined b2

上面代码中,forEach方法的回调函数中的this,其实指向的是window对象,因此取不到keith.a的值,同上也属于避免多层嵌套this。也就是说,内层的this不指向外部函数,而是指向顶层对象。

要解决这个方法,可以使用that变量来代替回调函数中的this。

var keith = {
  a: 'Hello',
  b: ['b1', 'b2'],
  c: function() {
   var that = this;
   this.b.forEach(function(item) {
    console.log(that.a + ' ' + item);
   })
  }
 };
 keith.c();
 //Hello b1
 //Hello b2

另外一种方法,就是让this做为forEach方法的第二个参数,来固定它的运行环境。

var keith = {
  a: 'Hello',
  b: ['b1', 'b2'],
  c: function() {
   this.b.forEach(function(item) {
    console.log(this.a + ' ' + item);
   }, this)
  }
 };
 keith.c();
 //Hello b1
 //Hello b2

3.3:避免回调函数中的this

回调函数中的this往往会改变指向。

var o = {
  f: function() {
   console.log(this === o);
  }
 };
 o.f(); // true;

上面代码中,调用o对象的f方法,返回true。

但是,如果将f方法指定给某个按钮的click事件,this的指向就变了。

$('button').on('click',o.f);

上面代码中,使用了jquery方法来获取button元素,并绑定click事件。点击按钮后控制台会显示false。原因是此时this不再指向o对象了,而是指向按钮的DOM对象,因为f方法是在按钮对象的环境中被调用的。

总结一下:

a:如果想要多层嵌套this关键字,最常用的解决方法就是使用that变量,固定指向外层的this,然后在内层中使用that变量。就不会发生内层this指向全局的问题。

b:如果在回调函数中使用this关键字,注意this的指向问题。


Déclaration:
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