Comment fonctionne le mot-clé «this»?

1310

J'ai remarqué qu'il ne semble pas y avoir d'explication claire de ce que la this mot-clé et comment il est correctement (et incorrectement) utilisé en JavaScript sur le site Stack Overflow.

J'ai été témoin d'un comportement très étrange avec cela et je n'ai pas compris pourquoi cela s'est produit.

Comment thisfonctionne et quand doit-il être utilisé?

Maxim Gershkovich
la source
6
J'ai trouvé cela quand j'ai googlé "this" sur quirksmode.org/js/this.html
Wai Wong
2
Peter Michaux plaide contre l'utilisation de this peter.michaux.ca/articles/javascript-widgets-without-this
Marcel Korpel
1
La vue d'ensemble de MDN n'est pas à moitié mauvaise ... developer.mozilla.org/en-US/docs/JavaScript/Reference/Operators/…
dat
2
Une explication intéressante du thismot - clé: rainsoft.io/gentle-explanation-of-this-in-javascript
Dmitri Pavlutin

Réponses:

1351

Je recommande de lire d'abord l' article Scope de Mike West en JavaScript ( miroir ). C'est une excellente introduction conviviale aux concepts dethis et aux chaînes de portée en JavaScript.

Une fois que vous commencez à vous y habituer this, les règles sont en fait assez simples. La norme ECMAScript 5.1 définit this:

§11.1.1 Le thismot-clé

Le thismot clé évalue la valeur de ThisBinding du contexte d'exécution actuel

ThisBinding est quelque chose que l'interpréteur JavaScript maintient pendant qu'il évalue le code JavaScript, comme un registre CPU spécial qui contient une référence à un objet. L'interpréteur met à jour ThisBinding chaque fois que vous établissez un contexte d'exécution dans l'un des trois cas différents uniquement:

1. Contexte d'exécution global initial

C'est le cas du code JavaScript évalué au niveau supérieur, par exemple lorsqu'il est directement à l'intérieur d'un <script>:

<script>
  alert("I'm evaluated in the initial global execution context!");

  setTimeout(function () {
      alert("I'm NOT evaluated in the initial global execution context.");
  }, 1);
</script>

Lors de l'évaluation du code dans le contexte d'exécution global initial, ThisBinding est défini sur l'objet global window( §10.4.1.1 ).

Saisie du code d'évaluation

  • … Par un appel direct à eval() ThisBinding reste inchangé; c'est la même valeur que ThisBinding du contexte d'exécution appelant ( §10.4.2 (2) (a)).

  • eval()
    Sinon par un appel direct à ThisBinding est défini sur l'objet global comme s'il s'exécutait dans le contexte d'exécution global initial ( §10.4.2 (1)).

Le §15.1.2.1.1 définit ce qu'est un appel direct eval(). Fondamentalement, eval(...)est un appel direct alors que quelque chose comme (0, eval)(...)ou var indirectEval = eval; indirectEval(...);est un appel indirect à eval(). Voir la réponse de chuckj à (1, eval) ('ceci') vs eval ('ceci') en JavaScript? et ECMA-262-5 de Dmitry Soshnikov en détail. Chapitre 2. Mode strict. pour savoir quand vous pourriez utiliser un eval()appel indirect .

Saisie du code de fonction

Cela se produit lors de l'appel d'une fonction. Si une fonction est appelée sur un objet, comme dans obj.myMethod()ou l'équivalent obj["myMethod"](), ThisBinding est défini sur l'objet ( objdans l'exemple; §13.2.1 ). Dans la plupart des autres cas, ThisBinding est défini sur l'objet global ( §10.4.3 ).

La raison de l'écriture «dans la plupart des autres cas» est qu'il existe huit fonctions intégrées ECMAScript 5 qui permettent de spécifier ThisBinding dans la liste des arguments. Ces fonctions spéciales prennent ce qu'on appelle thisArgce qui devient ThisBinding lors de l'appel de la fonction ( §10.4.3 ).

Ces fonctions intégrées spéciales sont:

  • Function.prototype.apply( thisArg, argArray )
  • Function.prototype.call( thisArg [ , arg1 [ , arg2, ... ] ] )
  • Function.prototype.bind( thisArg [ , arg1 [ , arg2, ... ] ] )
  • Array.prototype.every( callbackfn [ , thisArg ] )
  • Array.prototype.some( callbackfn [ , thisArg ] )
  • Array.prototype.forEach( callbackfn [ , thisArg ] )
  • Array.prototype.map( callbackfn [ , thisArg ] )
  • Array.prototype.filter( callbackfn [ , thisArg ] )

Dans le cas des Function.prototypefonctions, elles sont appelées sur un objet fonction, mais plutôt que de définir ThisBinding sur l'objet fonction, ThisBinding est défini surthisArg .

Dans le cas des Array.prototypefonctions, la donnée callbackfnest appelée dans un contexte d'exécution où ThisBinding est défini sur thisArgsi fourni; sinon, à l'objet global.

Ce sont les règles du JavaScript simple. Lorsque vous commencez à utiliser des bibliothèques JavaScript (par exemple jQuery), vous pouvez constater que certaines fonctions de bibliothèque manipulent la valeur de this. Les développeurs de ces bibliothèques JavaScript le font car il a tendance à prendre en charge les cas d'utilisation les plus courants, et les utilisateurs de la bibliothèque trouvent généralement ce comportement plus pratique. Lorsque vous transmettez des fonctions de rappel faisant référence thisà des fonctions de bibliothèque, vous devez vous référer à la documentation pour toutes les garanties sur la valeur de thislorsque la fonction est appelée.

Si vous vous demandez comment une bibliothèque JavaScript manipule la valeur de this, la bibliothèque utilise simplement l'une des fonctions JavaScript intégrées acceptant a thisArg. Vous pouvez également écrire votre propre fonction en utilisant une fonction de rappel et thisArg:

function doWork(callbackfn, thisArg) {
    //...
    if (callbackfn != null) callbackfn.call(thisArg);
}

Il y a un cas particulier que je n'ai pas encore mentionné. Lors de la construction d'un nouvel objet via l' newopérateur, l'interpréteur JavaScript crée un nouvel objet vide, définit certaines propriétés internes, puis appelle la fonction constructeur sur le nouvel objet. Ainsi, lorsqu'une fonction est appelée dans un contexte constructeur, la valeur de thisest le nouvel objet créé par l'interpréteur:

function MyType() {
    this.someData = "a string";
}

var instance = new MyType();
// Kind of like the following, but there are more steps involved:
// var instance = {};
// MyType.call(instance);

Fonctions fléchées

Les fonctions fléchées (introduites dans ECMA6) modifient la portée de this. Voir la question canonique existante, fonction flèche vs déclaration / expressions de fonction: sont-elles équivalentes / échangeables? pour plus d'informations. Mais en bref:

Les fonctions fléchées n'ont pas leur propre this... liaison. Au lieu de cela, ces identificateurs sont résolus dans la portée lexicale comme toute autre variable. Cela signifie qu'à l'intérieur d'une fonction flèche, this... se référer aux valeurs de thisl'environnement dans lequel la fonction flèche est définie.

Juste pour le plaisir, testez votre compréhension avec quelques exemples

Pour révéler les réponses, passez la souris sur les cases gris clair.

  1. Quelle est la valeur de thisla ligne marquée? Pourquoi?

    window - La ligne marquée est évaluée dans le contexte d'exécution global initial.

    if (true) {
        // What is `this` here?
    }
  2. Quelle est la valeur de thisla ligne marquée lors de l' obj.staticFunction()exécution? Pourquoi?

    obj - Lors de l'appel d'une fonction sur un objet, ThisBinding est défini sur l'objet.

    var obj = {
        someData: "a string"
    };
    
    function myFun() {
        return this // What is `this` here?
    }
    
    obj.staticFunction = myFun;
    
    console.log("this is window:", obj.staticFunction() == window);
    console.log("this is obj:", obj.staticFunction() == obj);
      

  3. Quelle est la valeur de thisla ligne marquée? Pourquoi?

    window

    Dans cet exemple, l'interpréteur JavaScript entre le code de fonction, mais parce que myFun/ obj.myMethodn'est pas appelé sur un objet, ThisBinding est défini sur window.

    Ceci est différent de Python, dans lequel l'accès à une méthode ( obj.myMethod) crée un objet de méthode lié .

    var obj = {
        myMethod: function () {
            return this; // What is `this` here?
        }
    };
    var myFun = obj.myMethod;
    console.log("this is window:", myFun() == window);
    console.log("this is obj:", myFun() == obj);
      

  4. Quelle est la valeur de thisla ligne marquée? Pourquoi?

    window

    Celui-ci était délicat. Lors de l'évaluation du code eval, thisest obj. Cependant, dans le code eval, myFunn'est pas appelé sur un objet, donc ThisBinding est défini sur windowpour l'appel.

    function myFun() {
        return this; // What is `this` here?
    }
    var obj = {
        myMethod: function () {
            eval("myFun()");
        }
    };
  5. Quelle est la valeur de thisla ligne marquée? Pourquoi?

    obj

    La ligne myFun.call(obj);appelle la fonction intégrée spéciale Function.prototype.call(), qui accepte thisArgcomme premier argument.

    function myFun() {
        return this; // What is `this` here?
    }
    var obj = {
        someData: "a string"
    };
    console.log("this is window:", myFun.call(obj) == window);
    console.log("this is obj:", myFun.call(obj) == obj);
      

Daniel Trebbien
la source
6
@Ali: Ce sont des références aux sections de l'édition 5.1 de la norme ECMAScript, ECMA-262 . Je les fournis afin que vous puissiez lire la norme pour les détails techniques si vous le souhaitez.
Daniel Trebbien
1
Je pense que @supertonsky a raison sur # 2 - si myFun () est appelé à partir de la portée globale, et non comme méthode sur l'objet, "ceci" sera l'objet global, donc la formulation de la question est importante. btw - J'aime vraiment l'idée d'utiliser mouseover pour obtenir la réponse à quelque chose comme ça.
user655489
2
Mais, jsfiddle.net/H4LYm/2 montre que l' setTimeoutexemple a un thisde window(global).
Kevin Meredith
2
venant de Python, on pourrait imaginer les niveaux de frustration que j'avais quand je suis tombé sur le 3ème exemple .. smh
Marius Mucenicu
1
Cette réponse devrait probablement être mise à jour pour refléter la réalité ES2020, même si les changements ne sont que terminologiques.
Ben Aston
157

Le thismot clé se comporte différemment en JavaScript par rapport à d'autres langues. Dans les langages orientés objet, le thismot - clé fait référence à l'instance actuelle de la classe. En JavaScript, la valeur de thisest déterminée par le contexte d'invocation de la fonction ( context.function()) et l'endroit où elle est appelée.

1. Lorsqu'il est utilisé dans un contexte mondial

Lorsque vous utilisez thisdans un contexte global, il est lié à un objet global ( windowdans le navigateur)

document.write(this);  //[object Window]

Lorsque vous utilisez à l' thisintérieur d'une fonction définie dans le contexte global, thisest toujours lié à un objet global car la fonction est en fait une méthode de contexte global.

function f1()
{
   return this;
}
document.write(f1());  //[object Window]

Ci f1- dessus est faite une méthode d'objet global. Ainsi, nous pouvons également l'appeler sur l' windowobjet comme suit:

function f()
{
    return this;
}

document.write(window.f()); //[object Window]

2. Lorsqu'il est utilisé à l'intérieur de la méthode objet

Lorsque vous utilisez un thismot clé dans une méthode objet, thisest lié à l'objet englobant "immédiat".

var obj = {
    name: "obj",
    f: function () {
        return this + ":" + this.name;
    }
};
document.write(obj.f());  //[object Object]:obj

Ci-dessus, j'ai mis le mot immédiat entre guillemets. Cela signifie que si vous imbriquez l'objet dans un autre objet, il thisest lié au parent immédiat.

var obj = {
    name: "obj1",
    nestedobj: {
        name:"nestedobj",
        f: function () {
            return this + ":" + this.name;
        }
    }            
}

document.write(obj.nestedobj.f()); //[object Object]:nestedobj

Même si vous ajoutez explicitement une fonction à l'objet en tant que méthode, elle suit toujours les règles ci-dessus, c'est-à-dire thispointe vers l'objet parent immédiat.

var obj1 = {
    name: "obj1",
}

function returnName() {
    return this + ":" + this.name;
}

obj1.f = returnName; //add method to object
document.write(obj1.f()); //[object Object]:obj1

3. Lors de l'appel de la fonction sans contexte

Lorsque vous utilisez une thisfonction interne invoquée sans aucun contexte (c'est-à-dire pas sur un objet), elle est liée à l'objet global ( windowdans le navigateur) (même si la fonction est définie à l'intérieur de l'objet).

var context = "global";

var obj = {  
    context: "object",
    method: function () {                  
        function f() {
            var context = "function";
            return this + ":" +this.context; 
        };
        return f(); //invoked without context
    }
};

document.write(obj.method()); //[object Window]:global 

Tout essayer avec des fonctions

Nous pouvons également essayer les points ci-dessus avec des fonctions. Il existe cependant quelques différences.

  • Ci-dessus, nous avons ajouté des membres aux objets en utilisant la notation littérale des objets. Nous pouvons ajouter des membres aux fonctions en utilisant this. pour les préciser.
  • La notation littérale d'objet crée une instance d'objet que nous pouvons utiliser immédiatement. Avec la fonction, nous devrons peut-être d'abord créer son instance à l'aide de l' newopérateur.
  • Toujours dans une approche littérale d'objet, nous pouvons explicitement ajouter des membres à un objet déjà défini en utilisant l'opérateur point. Cela est ajouté à l'instance spécifique uniquement. Cependant, j'ai ajouté une variable au prototype de fonction afin qu'elle se reflète dans toutes les instances de la fonction.

Ci-dessous, j'ai essayé toutes les choses que nous avons faites avec Object et thisci - dessus, mais en créant d'abord une fonction au lieu d'écrire directement un objet.

/********************************************************************* 
  1. When you add variable to the function using this keyword, it 
     gets added to the function prototype, thus allowing all function 
     instances to have their own copy of the variables added.
*********************************************************************/
function functionDef()
{
    this.name = "ObjDefinition";
    this.getName = function(){                
        return this+":"+this.name;
    }
}        

obj1 = new functionDef();
document.write(obj1.getName() + "<br />"); //[object Object]:ObjDefinition   

/********************************************************************* 
   2. Members explicitly added to the function protorype also behave 
      as above: all function instances have their own copy of the 
      variable added.
*********************************************************************/
functionDef.prototype.version = 1;
functionDef.prototype.getVersion = function(){
    return "v"+this.version; //see how this.version refers to the
                             //version variable added through 
                             //prototype
}
document.write(obj1.getVersion() + "<br />"); //v1

/********************************************************************* 
   3. Illustrating that the function variables added by both above 
      ways have their own copies across function instances
*********************************************************************/
functionDef.prototype.incrementVersion = function(){
    this.version = this.version + 1;
}
var obj2 = new functionDef();
document.write(obj2.getVersion() + "<br />"); //v1

obj2.incrementVersion();      //incrementing version in obj2
                              //does not affect obj1 version

document.write(obj2.getVersion() + "<br />"); //v2
document.write(obj1.getVersion() + "<br />"); //v1

/********************************************************************* 
   4. `this` keyword refers to the immediate parent object. If you 
       nest the object through function prototype, then `this` inside 
       object refers to the nested object not the function instance
*********************************************************************/
functionDef.prototype.nestedObj = { name: 'nestedObj', 
                                    getName1 : function(){
                                        return this+":"+this.name;
                                    }                            
                                  };

document.write(obj2.nestedObj.getName1() + "<br />"); //[object Object]:nestedObj

/********************************************************************* 
   5. If the method is on an object's prototype chain, `this` refers 
      to the object the method was called on, as if the method was on 
      the object.
*********************************************************************/
var ProtoObj = { fun: function () { return this.a } };
var obj3 = Object.create(ProtoObj); //creating an object setting ProtoObj
                                    //as its prototype
obj3.a = 999;                       //adding instance member to obj3
document.write(obj3.fun()+"<br />");//999
                                    //calling obj3.fun() makes 
                                    //ProtoObj.fun() to access obj3.a as 
                                    //if fun() is defined on obj3

4. Lorsqu'il est utilisé dans la fonction constructeur .

Lorsque la fonction est utilisée comme constructeur (c'est-à-dire lorsqu'elle est appelée avec un newmot-clé), le thiscorps de la fonction interne pointe vers le nouvel objet en cours de construction.

var myname = "global context";
function SimpleFun()
{
    this.myname = "simple function";
}

var obj1 = new SimpleFun(); //adds myname to obj1
//1. `new` causes `this` inside the SimpleFun() to point to the
//   object being constructed thus adding any member
//   created inside SimipleFun() using this.membername to the
//   object being constructed
//2. And by default `new` makes function to return newly 
//   constructed object if no explicit return value is specified

document.write(obj1.myname); //simple function

5. Lorsqu'il est utilisé à l'intérieur d'une fonction définie sur la chaîne du prototype

Si la méthode se trouve sur la chaîne prototype d'un objet, à l' thisintérieur d'une telle méthode fait référence à l'objet auquel la méthode a été appelée, comme si la méthode était définie sur l'objet.

var ProtoObj = {
    fun: function () {
        return this.a;
    }
};
//Object.create() creates object with ProtoObj as its
//prototype and assigns it to obj3, thus making fun() 
//to be the method on its prototype chain

var obj3 = Object.create(ProtoObj);
obj3.a = 999;
document.write(obj3.fun()); //999

//Notice that fun() is defined on obj3's prototype but 
//`this.a` inside fun() retrieves obj3.a   

6. Fonctions internes call (), apply () et bind ()

  • Toutes ces méthodes sont définies sur Function.prototype.
  • Ces méthodes permettent d'écrire une fonction une fois et de l'invoquer dans un contexte différent. En d'autres termes, ils permettent de spécifier la valeur thisqui sera utilisée lors de l'exécution de la fonction. Ils prennent également tous les paramètres à transmettre à la fonction d'origine lors de son appel.
  • fun.apply(obj1 [, argsArray])Définit obj1comme la valeur de thisinside fun()et appelle fun()les éléments de passage de argsArraycomme arguments.
  • fun.call(obj1 [, arg1 [, arg2 [,arg3 [, ...]]]])- Définit obj1comme la valeur de thisinside fun()et les appels fun()passant arg1, arg2, arg3, ...comme arguments.
  • fun.bind(obj1 [, arg1 [, arg2 [,arg3 [, ...]]]])- Renvoie la référence à la fonction funavec thisfun intérieur lié à obj1et paramètres de funlié aux paramètres spécifiés arg1, arg2, arg3,....
  • Désormais, la différence entre apply, callet binddoit être devenue apparente. applypermet de spécifier les arguments pour fonctionner comme un objet de type tableau, c'est-à-dire un objet avec une lengthpropriété numérique et des propriétés entières non négatives correspondantes. Alors que callpermet de spécifier directement les arguments de la fonction. Les deux applyet callinvoque immédiatement la fonction dans le contexte spécifié et avec les arguments spécifiés. En revanche, bindrenvoie simplement la fonction liée à la thisvaleur spécifiée et aux arguments. Nous pouvons capturer la référence à cette fonction retournée en l'affectant à une variable et plus tard, nous pouvons l'appeler à tout moment.
function add(inc1, inc2)
{
    return this.a + inc1 + inc2;
}

var o = { a : 4 };
document.write(add.call(o, 5, 6)+"<br />"); //15
      //above add.call(o,5,6) sets `this` inside
      //add() to `o` and calls add() resulting:
      // this.a + inc1 + inc2 = 
      // `o.a` i.e. 4 + 5 + 6 = 15
document.write(add.apply(o, [5, 6]) + "<br />"); //15
      // `o.a` i.e. 4 + 5 + 6 = 15

var g = add.bind(o, 5, 6);       //g: `o.a` i.e. 4 + 5 + 6
document.write(g()+"<br />");    //15

var h = add.bind(o, 5);          //h: `o.a` i.e. 4 + 5 + ?
document.write(h(6) + "<br />"); //15
      // 4 + 5 + 6 = 15
document.write(h() + "<br />");  //NaN
      //no parameter is passed to h()
      //thus inc2 inside add() is `undefined`
      //4 + 5 + undefined = NaN</code>

7. thisgestionnaires d'événements internes

  • Lorsque vous affectez une fonction directement aux gestionnaires d'événements d'un élément, l'utilisation de thisla fonction de gestion d'événements directement à l'intérieur fait référence à l'élément correspondant. Une telle affectation directe de fonction peut être effectuée en utilisant la addeventListenerméthode ou par les méthodes d'enregistrement d'événements traditionnelles comme onclick.
  • De même, lorsque vous utilisez thisdirectement à l'intérieur de la propriété d'événement (comme <button onclick="...this..." >) de l'élément, il fait référence à l'élément.
  • Cependant, l'utilisation thisindirecte via l'autre fonction appelée à l'intérieur de la fonction de gestion des événements ou de la propriété d'événement se résout en l'objet global window.
  • Le même comportement ci-dessus est obtenu lorsque nous attachons la fonction au gestionnaire d'événements à l'aide de la méthode du modèle d'enregistrement d'événements de Microsoft attachEvent. Au lieu d'affecter la fonction au gestionnaire d'événements (et donc de créer la méthode de fonction de l'élément), il appelle la fonction sur l'événement (l'appelle effectivement dans le contexte global).

Je recommande de mieux essayer ceci dans JSFiddle .

<script> 
    function clickedMe() {
       alert(this + " : " + this.tagName + " : " + this.id);
    } 
    document.getElementById("button1").addEventListener("click", clickedMe, false);
    document.getElementById("button2").onclick = clickedMe;
    document.getElementById("button5").attachEvent('onclick', clickedMe);   
</script>

<h3>Using `this` "directly" inside event handler or event property</h3>
<button id="button1">click() "assigned" using addEventListner() </button><br />
<button id="button2">click() "assigned" using click() </button><br />
<button id="button3" onclick="alert(this+ ' : ' + this.tagName + ' : ' + this.id);">used `this` directly in click event property</button>

<h3>Using `this` "indirectly" inside event handler or event property</h3>
<button onclick="alert((function(){return this + ' : ' + this.tagName + ' : ' + this.id;})());">`this` used indirectly, inside function <br /> defined & called inside event property</button><br />

<button id="button4" onclick="clickedMe()">`this` used indirectly, inside function <br /> called inside event property</button> <br />

IE only: <button id="button5">click() "attached" using attachEvent() </button>

8. thisdans la fonction flèche ES6

Dans une fonction flèche, thisse comportera comme des variables communes: elle sera héritée de sa portée lexicale. La fonction this, où la fonction flèche est définie, sera celle de la fonction flèche this.

Donc, c'est le même comportement que:

(function(){}).bind(this)

Voir le code suivant:

const globalArrowFunction = () => {
  return this;
};

console.log(globalArrowFunction()); //window

const contextObject = {
  method1: () => {return this},
  method2: function(){
    return () => {return this};
  }
};

console.log(contextObject.method1()); //window

const contextLessFunction = contextObject.method1;

console.log(contextLessFunction()); //window

console.log(contextObject.method2()()) //contextObject

const innerArrowFunction = contextObject.method2();

console.log(innerArrowFunction()); //contextObject 
Mahesha999
la source
"Lorsque vous l'utilisez dans une fonction définie dans le contexte global, cela est toujours lié à un objet global car la fonction est en fait une méthode de contexte global." est incorrect. elle est définie par la façon dont une fonction est appelée ou par liaison , et non par l'endroit où elle est définie. L' appel d' une fonction sans une référence de base ( « contexte ») sera par défaut ce à l'objet global ou rester non défini en mode strict.
RobG
@RobG hmm peut être, mais j'ai trouvé ceci sur MDN : Dans ce cas, la valeur de thisn'est pas définie par l'appel. Étant donné que le code n'est pas en mode strict, la valeur de thisdoit toujours être un objet, il est donc défini par défaut sur l'objet global. Et en fait, c'est pourquoi j'ai pensé que nous pouvions appeler directement window.f1(), de sorte que les moyens f1()sont déjà attachés à l' windowobjet, je veux dire avant l'invocation. Suis-je en train de me tromper?
Mahesha999
Je commentais (peut-être pas clairement) votre lien entre le réglage de ceci et "la fonction est en fait une méthode du contexte global", comme si elle était en quelque sorte appelée window.fn, ce qui n'est pas le cas. cela signifie par défaut l'objet global car aucune référence de base n'a été utilisée dans l'appel, pas à cause de l'endroit où la fonction est définie (donc cela est toujours défini par la façon dont la fonction a été appelée). Si vous l'appelez explicitement à l'aide window.fn, vous définissez cette option sur fenêtre . Même résultat, façon différente de procéder. :-)
RobG
"ci-dessus j'ai mis le mot immédiat ..." non tu ne l'as pas fait. Pouvez-vous s'il vous plaît réviser cela afin que l'erreur soit corrigée? Cela semble sémantique à la réponse et donc je ne peux pas continuer à lire jusqu'à ce que l'erreur soit corrigée de peur d'apprendre quelque chose de incorrect.
TylerH
@TylerH faire Ctrl + F sur cette page dans votre navigateur pour trouver la chaîne "immédiate" (y compris les guillemets doubles) Je pense que c'est là si je comprends mal
Mahesha999
64

Javascript this

Appel de fonction simple

Considérez la fonction suivante:

function foo() {
    console.log("bar");
    console.log(this);
}
foo(); // calling the function

Notez que nous l'exécutons en mode normal, c'est-à-dire que le mode strict n'est pas utilisé.

Lors de l'exécution dans un navigateur, la valeur de thisserait enregistrée sous window. C'est parce que windowc'est la variable globale dans la portée d'un navigateur Web.

Si vous exécutez ce même morceau de code dans un environnement comme node.js, thisferait référence à la variable globale dans votre application.

Maintenant, si nous l'exécutons en mode strict en ajoutant l'instruction "use strict";au début de la déclaration de fonction, thisne ferait plus référence à la variable globale dans aucun des environnements. Ceci est fait pour éviter les confusions en mode strict. thisserait, dans ce cas, simplement se connecter undefined, car c'est ce qu'il est, il n'est pas défini.

Dans les cas suivants, nous verrions comment manipuler la valeur de this.

Appel d'une fonction sur un objet

il y a différentes facons de faire cela. Si vous avez appelé des méthodes natives en Javascript comme forEachet slice, vous devez déjà savoir que la thisvariable dans ce cas fait référence à celle Objectsur laquelle vous avez appelé cette fonction (notez qu'en javascript, à peu près tout est un Object, y compris Arrays et Functions). Prenons l'exemple du code suivant.

var myObj = {key: "Obj"};
myObj.logThis = function () {
    // I am a method
    console.log(this);
}
myObj.logThis(); // myObj is logged

Si un Objectcontient une propriété qui contient un Function, la propriété est appelée une méthode. Cette méthode, lorsqu'elle est appelée, aura toujours sa thisvariable définie sur la valeur à laquelle Objectelle est associée. Cela est vrai pour les modes stricts et non stricts.

Notez que si une méthode est stockée (ou plutôt copiée) dans une autre variable, la référence à thisn'est plus conservée dans la nouvelle variable. Par exemple:

// continuing with the previous code snippet

var myVar = myObj.logThis;
myVar();
// logs either of window/global/undefined based on mode of operation

Considérant un scénario plus couramment pratique:

var el = document.getElementById('idOfEl');
el.addEventListener('click', function() { console.log(this) });
// the function called by addEventListener contains this as the reference to the element
// so clicking on our element would log that element itself

Le newmot clé

Considérons une fonction constructeur en Javascript:

function Person (name) {
    this.name = name;
    this.sayHello = function () {
        console.log ("Hello", this);
    }
}

var awal = new Person("Awal");
awal.sayHello();
// In `awal.sayHello`, `this` contains the reference to the variable `awal`

Comment cela marche-t-il? Voyons ce qui se passe lorsque nous utilisons le newmot - clé.

  1. L'appel de la fonction avec le newmot clé initialiserait immédiatement un Objecttype Person.
  2. Le constructeur de ceci Objecta son constructeur réglé sur Person. Notez également que cela typeof awalne reviendra Objectque.
  3. Ce nouveau se Objectverrait attribuer le prototype de Person.prototype. Cela signifie que toute méthode ou propriété du Personprototype serait disponible pour toutes les instances de Person, y compris awal.
  4. La fonction Personelle-même est maintenant invoquée; thisétant une référence à l'objet nouvellement construit awal.

Assez simple, hein?

Notez que la spécification ECMAScript officielle n'indique nulle part que ces types de fonctions sont des constructorfonctions réelles . Ce ne sont que des fonctions normales et newpeuvent être utilisées sur n'importe quelle fonction. C'est juste que nous les utilisons en tant que tels, et donc nous les appelons uniquement en tant que tels.

Appeler des fonctions sur les fonctions: calletapply

Donc oui, puisque les functions le sont aussi Objects(et en fait les variables de première classe en Javascript), même les fonctions ont des méthodes qui sont ... eh bien, les fonctions elles-mêmes.

Toutes les fonctions héritent du global Function, et deux de ses nombreuses méthodes sont callet apply, et les deux peuvent être utilisées pour manipuler la valeur de thisdans la fonction sur laquelle elles sont appelées.

function foo () { console.log (this, arguments); }
var thisArg = {myObj: "is cool"};
foo.call(thisArg, 1, 2, 3);

Ceci est un exemple typique d'utilisation call. Il prend essentiellement le premier paramètre et définit thisla fonction foocomme référence thisArg. Tous les autres paramètres passés à callsont passés à la fonction foocomme arguments.
Le code ci-dessus se connectera donc {myObj: "is cool"}, [1, 2, 3]à la console. Très belle façon de changer la valeur de thisn'importe quelle fonction.

applyéquivaut presque à callaccepter qu'il ne prend que deux paramètres: thisArget un tableau qui contient les arguments à passer à la fonction. Ainsi, l' callappel ci - dessus peut être traduit applycomme ceci:

foo.apply(thisArg, [1,2,3])

Notez que callet applypeut remplacer la valeur de l' thisinvocation de la méthode set by dot dont nous avons parlé dans la deuxième puce. Assez simple :)

Présentation .... bind!

bindest un frère de callet apply. C'est également une méthode héritée par toutes les fonctions du Functionconstructeur global en Javascript. La différence entre bindet call/ applyest que les deux callet applyinvoqueront réellement la fonction. bind, d'autre part, retourne une nouvelle fonction avec le thisArget argumentspréréglé. Prenons un exemple pour mieux comprendre ceci:

function foo (a, b) {
    console.log (this, arguments);
}
var thisArg = {myObj: "even more cool now"};
var bound = foo.bind(thisArg, 1, 2);
console.log (typeof bound); // logs `function`
console.log (bound);
/* logs `function () { native code }` */

bound(); // calling the function returned by `.bind`
// logs `{myObj: "even more cool now"}, [1, 2]`

Voyez la différence entre les trois? C'est subtil, mais ils sont utilisés différemment. Comme callet apply, bindoutrepassera également la valeur de thisset by invocation méthode dot.

Notez également qu'aucune de ces trois fonctions ne modifie la fonction d'origine. callet applyretournerait la valeur des fonctions fraîchement construites tandis que bindretournera la fonction fraîchement construite elle-même, prête à être appelée.

Des trucs supplémentaires, copiez ceci

Parfois, vous n'aimez pas le fait que les thismodifications avec la portée, en particulier la portée imbriquée. Jetez un œil à l'exemple suivant.

var myObj = {
    hello: function () {
        return "world"
        },
    myMethod: function () {
        // copy this, variable names are case-sensitive
        var that = this;
        // callbacks ftw \o/
        foo.bar("args", function () {
            // I want to call `hello` here
            this.hello(); // error
            // but `this` references to `foo` damn!
            // oh wait we have a backup \o/
            that.hello(); // "world"
        });
    }
  };

Dans le code ci-dessus, nous voyons que la valeur de a thischangé avec la portée imbriquée, mais nous voulions la valeur de thisla portée d'origine. Nous avons donc « copié » thisà thatet utilisé la copie au lieu de this. Intelligent, hein?

Indice:

  1. Que contient-il thispar défaut?
  2. Que se passe-t-il si nous appelons la fonction en tant que méthode avec la notation Object-dot?
  3. Et si nous utilisons le newmot-clé?
  4. Comment manipulons-nous thisavec callet apply?
  5. Utilisation bind.
  6. Copie thispour résoudre les problèmes de portée imbriquée.
user3459110
la source
47

"ceci" est une question de portée. Chaque fonction a sa propre portée, et puisque tout dans JS est un objet, même une fonction peut stocker certaines valeurs en elle-même en utilisant "ceci". La POO 101 enseigne que "ceci" ne s'applique qu'aux instances d'un objet. Par conséquent, chaque fois qu'une fonction s'exécute, une nouvelle "instance" de cette fonction a une nouvelle signification de "ceci".

La plupart des gens sont confus lorsqu'ils essaient d'utiliser "ceci" dans des fonctions de fermeture anonymes comme:

(fonction (valeur) {
    this.value = valeur;
    $ ('. certains-éléments'). each (fonction (elt) {
        elt.innerHTML = this.value; // euh oh !! éventuellement indéfini
    });
}) (2);

Donc ici, à l'intérieur de chaque (), "ceci" ne contient pas la "valeur" à laquelle vous vous attendez (de

this.value = valeur;
Au dessus de). Donc, pour surmonter ce problème (sans jeu de mots), un développeur pourrait:

(fonction (valeur) {
    var self = this; // petite monnaie
    self.value = valeur;
    $ ('. certains-éléments'). each (fonction (elt) {
        elt.innerHTML = self.value; // phew!! == 2
    });
}) (2);

Essaye le; vous commencerez à aimer ce schéma de programmation

arunjitsingh
la source
6
"tout dans JS est un objet" n'est pas vrai, JavaScript a aussi des valeurs primitives, voir bclary.com/2004/11/07/#a-4.3.2
Marcel Korpel
6
Les valeurs primitives semblent avoir certaines méthodes sur elles-mêmes, comme String # substring (), Number # toString (), etc. Donc, peut-être pas avec la même nomenclature que cet article, elles se comportent vraiment comme si elles étaient des objets (elles sont tout prototypé, c'est-à-dire que String # substring () est vraiment: String.prototype.substring = function () {...}). Corrigez-moi si j'ai tort, s'il-vous plait.
arunjitsingh
12
Le thismot-clé n'a rien à voir avec la portée. En outre, il a également une signification dans les fonctions qui ne sont pas des propriétés d'objets.
Bergi
1
@ arunjitsingh - il y a deux écoles de pensée à ce sujet. J'aime celui qui dit " tout est un objet, mais certains peuvent être représentés par des primitives pour plus de commodité ". ;-)
RobG
9
thisn'est pas TOUT sur la portée. Tout dépend du contexte d'exécution, ce qui n'est pas la même chose que la portée. JavaScript a une portée lexicale (ce qui signifie que la portée est déterminée par l'emplacement du code), mais thisest déterminée par la façon dont la fonction qui le contient est invoquée - et non par l'emplacement de cette fonction.
Scott Marcus
16

Depuis ce fil a augmenté, j'ai compilé quelques points pour les lecteurs nouveaux sur le thissujet.

Comment la valeur de est-elle thisdéterminée?

Nous utilisons cela de la même manière que nous utilisons les pronoms dans les langues naturelles comme l'anglais: "John court vite parce qu'il essaie d'attraper le train." Au lieu de cela, nous aurions pu écrire «… John essaie de prendre le train».

var person = {    
    firstName: "Penelope",
    lastName: "Barrymore",
    fullName: function () {

    // We use "this" just as in the sentence above:
       console.log(this.firstName + " " + this.lastName);

    // We could have also written:
       console.log(person.firstName + " " + person.lastName);
    }
}

this ne reçoit pas de valeur tant qu'un objet n'appelle pas la fonction où il est défini. Dans la portée globale, toutes les variables et fonctions globales sont définies sur l' windowobjet. Par conséquent, thisdans une fonction globale fait référence à (et a la valeur de) l' windowobjet global .

Lorsque use strict, thisdans les fonctions globales et anonymes qui ne sont liées à aucun objet, contient une valeur de undefined.

Le thismot-clé est le plus mal compris lorsque: 1) nous empruntons une méthode qui utilise this, 2) nous attribuons une méthode qui utilise thisà une variable, 3) une fonction qui utilise thisest passée en tant que fonction de rappel, et 4) thisest utilisée à l'intérieur d'une fermeture - une fonction intérieure. (2)

table

Ce qui nous réserve l'avenir

Définies dans ECMA Script 6 , les fonctions fléchées adoptent la thisliaison de l'étendue englobante (fonction ou globale).

function foo() {
     // return an arrow function
     return (a) => {
     // `this` here is lexically inherited from `foo()`
     console.log(this.a);
  };
}
var obj1 = { a: 2 };
var obj2 = { a: 3 };

var bar = foo.call(obj1);
bar.call( obj2 ); // 2, not 3!

Bien que les fonctions fléchées offrent une alternative à l'utilisation bind(), il est important de noter qu'elles désactivent essentiellement le thismécanisme traditionnel au profit d'une portée lexicale plus largement comprise. (1)


Références:

  1. this & Object Prototypes , par Kyle Simpson. © 2014 Getify Solutions.
  2. javascriptissexy.com - http://goo.gl/pvl0GX
  3. Angus Croll - http://goo.gl/Z2RacU
carlodurso
la source
16

thisen JavaScript fait toujours référence au «propriétaire» de la fonction en cours d'exécution .

Si aucun propriétaire explicite n'est défini, le propriétaire le plus haut, l'objet fenêtre, est référencé.

Donc si je le faisais

function someKindOfFunction() {
   this.style = 'foo';
}

element.onclick = someKindOfFunction;

thisferait référence à l'objet élément. Mais attention, beaucoup de gens font cette erreur.

<element onclick="someKindOfFunction()">

Dans ce dernier cas, vous vous contentez de référencer la fonction, pas de la remettre à l'élément. Par conséquent, thisfera référence à l'objet fenêtre.

Seph
la source
15

Chaque contexte d'exécution en javascript a un paramètre this défini par:

  1. Comment la fonction est appelée (y compris en tant que méthode d'objet, utilisation de call and apply , utilisation de new )
  2. Utilisation de bind
  3. Lexiquement pour les fonctions flèches (elles adoptent le présent de leur contexte d'exécution externe)
  4. Que le code soit en mode strict ou non strict
  5. Indique si le code a été invoqué à l'aide de eval

Vous pouvez définir la valeur de ceci en utilisant func.call, func.applyou func.bind.

Par défaut, et ce qui déroute la plupart des débutants, lorsqu'un écouteur est appelé après qu'un événement est déclenché sur un élément DOM, la valeur this de la fonction est l'élément DOM.

jQuery rend cela trivial à changer avec jQuery.proxy.

imbécile
la source
9
Il est un peu plus correct de dire que chaque appel de fonction a une portée. En d'autres termes, ce qui prête à confusion thisdans Javascript, c'est que ce n'est pas une propriété intrinsèque de la fonction elle-même, mais plutôt un artefact de la façon dont la fonction est invoquée.
Pointy
@pointy merci. ce qui cause le plus de confusion à ce sujet dans js est le fait que dans tous les langages utilisés précédemment (c #, c ++), - cela ne peut pas être manipulé n pointe toujours vers l'instance d'objet alors que dans js cela dépend et peut être changé lors de l'appel fonctions utilisant func.call, func.bindetc. - Sushil
Sushil
2
thisne fait pas référence à l'étendue d'une fonction. thisfera référence à un objet spécifique (ou éventuellement undefined), qui, comme vous l'avez dit, peut être modifié à l'aide de .call()ou .apply(). La portée d' une fonction est (essentiellement, lorsqu'elle est simplifiée) à quelles variables elle a accès, et cela dépend entièrement de l'endroit où la fonction est déclarée et ne peut pas être modifiée.
nnnnnn
@Pointy: "Il est un peu plus correct de dire que chaque appel de fonction a une portée." Encore plus correct de dire que les fonctions (et maintenant les blocs) ont une portée , les appels de fonction ont un contexte . La portée définit quels sont les identificateurs qui peuvent être utilisés par le code dans cette portée. Le contexte définit à quoi ces identifiants sont liés.
TJ Crowder
1
"Quelle que soit cette portée, elle est référencée par" ceci "." Non, thiset la portée n'a rien à voir avec ES5 et avant (par exemple, lorsque cette réponse a été écrite). Dans ES2015 (aka ES6), thiset la portée sont liées d' une manière assez minimale aux fonctions de flèche wrt (la fonction thisdans une flèche est héritée de sa portée englobante), mais thisne fait jamais référence à une portée.
TJ Crowder
10

Voici une bonne source de thisin JavaScript.

Voici le résumé:

  • ce mondial

    Dans un navigateur, à la portée globale, thisest l' windowobjet

    <script type="text/javascript">
      console.log(this === window); // true
      var foo = "bar";
      console.log(this.foo); // "bar"
      console.log(window.foo); // "bar"

    En nodeutilisant le repl, thisest l'espace de noms supérieur. Vous pouvez vous y référer comme global.

    >this
      { ArrayBuffer: [Function: ArrayBuffer],
        Int8Array: { [Function: Int8Array] BYTES_PER_ELEMENT: 1 },
        Uint8Array: { [Function: Uint8Array] BYTES_PER_ELEMENT: 1 },
        ...
    >global === this
     true

    Lors de l' nodeexécution à partir d'un script, thisla portée globale commence comme un objet vide. Ce n'est pas la même chose queglobal

    \\test.js
    console.log(this);  \\ {}
    console.log(this === global); \\ fasle
  • faire fonctionner cela

Sauf dans le cas des gestionnaires d'événements DOM ou lorsqu'un a thisArgest fourni (voir plus bas), à la fois dans le nœud et dans un navigateur utilisant thisdans une fonction qui n'est pas appelée avec des newréférences la portée globale…

<script type="text/javascript">
    foo = "bar";

    function testThis() {
      this.foo = "foo";
    }

    console.log(this.foo); //logs "bar"
    testThis();
    console.log(this.foo); //logs "foo"
</script>

Si vous utilisez use strict;, auquel cas thisseraundefined

<script type="text/javascript">
    foo = "bar";

    function testThis() {
      "use strict";
      this.foo = "foo";
    }

    console.log(this.foo); //logs "bar"
    testThis();  //Uncaught TypeError: Cannot set property 'foo' of undefined 
</script>

Si vous appelez une fonction avec newle thissera un nouveau contexte, il ne référencera pas le global this.

<script type="text/javascript">
    foo = "bar";

    function testThis() {
      this.foo = "foo";
    }

    console.log(this.foo); //logs "bar"
    new testThis();
    console.log(this.foo); //logs "bar"

    console.log(new testThis().foo); //logs "foo"
</script>
  • prototype ce

Les fonctions que vous créez deviennent des objets de fonction. Ils obtiennent automatiquement une prototypepropriété spéciale , à laquelle vous pouvez attribuer des valeurs. Lorsque vous créez une instance en appelant votre fonction avec, newvous avez accès aux valeurs que vous avez attribuées à la prototypepropriété. Vous accédez à ces valeurs à l'aide de this.

function Thing() {
  console.log(this.foo);
}

Thing.prototype.foo = "bar";

var thing = new Thing(); //logs "bar"
console.log(thing.foo);  //logs "bar"

C'est généralement une erreur d'attribuer des tableaux ou des objets sur le prototype. Si vous voulez que les instances aient chacune leurs propres tableaux, créez-les dans la fonction, pas dans le prototype.

function Thing() {
    this.things = [];
}

var thing1 = new Thing();
var thing2 = new Thing();
thing1.things.push("foo");
console.log(thing1.things); //logs ["foo"]
console.log(thing2.things); //logs []
  • objecter cela

Vous pouvez utiliser thisdans n'importe quelle fonction d'un objet pour faire référence à d'autres propriétés de cet objet. Ce n'est pas la même chose qu'une instance créée avec new.

var obj = {
    foo: "bar",
    logFoo: function () {
        console.log(this.foo);
    }
};

obj.logFoo(); //logs "bar"
  • Événement DOM ce

Dans un gestionnaire d'événements DOM HTML, thisest toujours une référence à l'élément DOM auquel l'événement a été attaché

function Listener() {
    document.getElementById("foo").addEventListener("click",
       this.handleClick);
}
Listener.prototype.handleClick = function (event) {
    console.log(this); //logs "<div id="foo"></div>"
}

var listener = new Listener();
document.getElementById("foo").click();

Sauf si vous bindle contexte

function Listener() {
    document.getElementById("foo").addEventListener("click", 
        this.handleClick.bind(this));
}
Listener.prototype.handleClick = function (event) {
    console.log(this); //logs Listener {handleClick: function}
}

var listener = new Listener();
document.getElementById("foo").click();
  • HTML ceci

À l'intérieur des attributs HTML dans lesquels vous pouvez mettre JavaScript, se thistrouve une référence à l'élément.

<div id="foo" onclick="console.log(this);"></div>
<script type="text/javascript">
document.getElementById("foo").click(); //logs <div id="foo"...
</script>
  • évaluer cela

Vous pouvez utiliser evalpour accéder this.

function Thing () {
}
Thing.prototype.foo = "bar";
Thing.prototype.logFoo = function () {
    eval("console.log(this.foo)"); //logs "bar"
}

var thing = new Thing();
thing.logFoo();
  • avec ça

Vous pouvez utiliser withpour ajouter thisà la portée actuelle pour lire et écrire sur des valeurs thissans faire référence thisexplicitement.

function Thing () {
}
Thing.prototype.foo = "bar";
Thing.prototype.logFoo = function () {
    with (this) {
        console.log(foo);
        foo = "foo";
    }
}

var thing = new Thing();
thing.logFoo(); // logs "bar"
console.log(thing.foo); // logs "foo"
  • jQuery this

la jQuery aura à de nombreux endroits fait thisréférence à un élément DOM.

<div class="foo bar1"></div>
<div class="foo bar2"></div>
<script type="text/javascript">
$(".foo").each(function () {
    console.log(this); //logs <div class="foo...
});
$(".foo").on("click", function () {
    console.log(this); //logs <div class="foo...
});
$(".foo").each(function () {
    this.click();
});
</script>
zangw
la source
9

Daniel, super explication! Quelques mots sur cela et une bonne liste de thispointeurs de contexte d'exécution en cas de gestionnaires d'événements.

En deux mots, thisen JavaScript pointe l'objet à partir duquel (ou à partir de quel contexte d'exécution) la fonction actuelle a été exécutée et elle est toujours en lecture seule, vous ne pouvez pas la définir de toute façon (une telle tentative se terminera par 'Invalid left-hand côté dans le message d'affectation.

Pour les gestionnaires d'événements: les gestionnaires d'événements en ligne, tels que <element onclick="foo">, remplacent tous les autres gestionnaires attachés plus tôt et avant, alors soyez prudent et il vaut mieux éviter la délégation d'événements en ligne. Et merci à Zara Alaverdyan qui m'a inspiré cette liste d'exemples à travers un débat dissident :)

  • el.onclick = foo; // in the foo - obj
  • el.onclick = function () {this.style.color = '#fff';} // obj
  • el.onclick = function() {doSomething();} // In the doSomething - Window
  • el.addEventListener('click',foo,false) // in the foo - obj
  • el.attachEvent('onclick, function () { // this }') // window, all the compliance to IE :)
  • <button onclick="this.style.color = '#fff';"> // obj
  • <button onclick="foo"> // In the foo - window, but you can <button onclick="foo(this)">
Arman McHitarian
la source
9

Il y a beaucoup de confusion quant à la façon dont "ce" mot clé est interprété en JavaScript. Espérons que cet article mettra tous ceux au repos une fois pour toutes. Et beaucoup plus. Veuillez lire attentivement l'intégralité de l'article. Soyez averti que cet article est long.

Quel que soit le contexte dans lequel il est utilisé, "this" fait toujours référence à "l'objet courant" en Javascript. Cependant, ce qu'est "l'objet courant" diffère selon le contexte . Le contexte peut être exactement 1 des 6 suivants:

  1. Global (c'est-à-dire en dehors de toutes les fonctions)
  2. Appel direct "Fonction non liée " interne (c'est-à-dire une fonction qui n'a pas été liée par l'appel de functionName.bind )
  3. À l'intérieur de la fonction indirecte "fonction non liée" via functionName.call et functionName.apply
  4. A l'intérieur de la fonction "Bound Function" (c'est-à-dire une fonction qui a été liée en appelant functionName.bind )
  5. Alors que la création d'objets à travers "nouveau"
  6. Gestionnaire d'événements Inside Inline DOM

Ce qui suit décrit chacun de ces contextes un par un:

  1. Contexte global (c'est-à-dire en dehors de toutes les fonctions):

    En dehors de toutes les fonctions (c'est-à-dire dans un contexte global), "l'objet courant" (et donc la valeur de "this" ) est toujours l' objet "window" pour les navigateurs.

  2. Appel direct "Fonction non liée" interne :

    Dans un appel direct à «fonction non liée», l'objet qui a appelé l'appel de fonction devient «l'objet actuel» (et donc la valeur de «ceci» ). Si une fonction est appelée sans objet courant explicite , l' objet courant est soit l' objet "fenêtre" (pour le mode non strict) soit indéfini (pour le mode strict). Toute fonction (ou variable) définie dans le contexte global devient automatiquement une propriété de l'objet "fenêtre" . Par exemple, supposons que la fonction soit définie dans le contexte global comme

    function UserDefinedFunction(){
        alert(this)
        }

    il devient la propriété de l'objet window, comme si vous l'aviez défini comme

    window.UserDefinedFunction=function(){
      alert(this)
    }  

    En "mode non strict", appeler / appeler cette fonction directement via "UserDefinedFunction ()" l'appellera / appellera automatiquement comme "window.UserDefinedFunction ()" faisant "window" comme "objet courant" (et donc la valeur de " ceci " ) dans " UserDefinedFunction ". L' invocation de cette fonction en" Mode non strict "entraînera ce qui suit

    UserDefinedFunction() // displays [object Window]  as it automatically gets invoked as window.UserDefinedFunction()

    En « Mode Strict », appel / Invoquer la fonction directement par « UserDefinedFunction () » sera « pas » appeler automatiquement / Invoke comme « window.UserDefinedFunction () » .Hence le « objet courant » (et la valeur de « cette » ) dans "UserDefinedFunction" ne doit pas être défini . L'appel de cette fonction en "mode strict" se traduira par ce qui suit

    UserDefinedFunction() // displays undefined

    Cependant, son invocation explicite à l'aide d'un objet window se traduira par ce qui suit

    window.UserDefinedFunction() // "always displays [object Window]   irrespective of mode."

    Voyons un autre exemple. Veuillez regarder le code suivant

     function UserDefinedFunction()
        {
            alert(this.a + ","  + this.b + ","  + this.c  + ","  + this.d)
        }
    
    var o1={
                a:1,
                b:2,
                f:UserDefinedFunction
          }
    var o2={
                c:3,
                d:4,
                f:UserDefinedFunction
           }
    
    o1.f() // Shall display 1,2,undefined,undefined
    o2.f() // Shall display undefined,undefined,3,4

    Dans l'exemple ci-dessus, nous voyons que lorsque "UserDefinedFunction" a été invoqué via o1 , "this" prend la valeur de o1 et la valeur de ses propriétés "a" et "b" s'affichent. La valeur de "c" et "d" était indiquée comme non définie car o1 ne définit pas ces propriétés

    De même lorsque "UserDefinedFunction" été invoqué via o2 , "this" prend la valeur de o2 et la valeur de ses propriétés "c" et "d" s'affichent. La valeur de "a" et "b" était indiquée comme non définie comme o2 le fait pas définir ces propriétés.

  3. Dans la fonction indirecte "Fonction non liée", appelez via functionName.call et functionName.apply :

    Lorsqu'un "fonction non liée" est appelée via functionName.call ou functionName.apply , l ' "objet actuel" (et donc la valeur de "this" ) est défini sur la valeur de "this" paramètre (premier paramètre) passé pour appeler / appliquer . Le code suivant illustre la même chose.

    function UserDefinedFunction()
    {
        alert(this.a + ","  + this.b + ","  + this.c  + ","  + this.d)
    }
    var o1={
                a:1,
                b:2,
                f:UserDefinedFunction
           }
    var o2={
                c:3,
                d:4,
                f:UserDefinedFunction
           }
    
    UserDefinedFunction.call(o1) // Shall display 1,2,undefined,undefined
    UserDefinedFunction.apply(o1) // Shall display 1,2,undefined,undefined
    
    UserDefinedFunction.call(o2) // Shall display undefined,undefined,3,4
    UserDefinedFunction.apply(o2) // Shall display undefined,undefined,3,4
    
    o1.f.call(o2) // Shall display undefined,undefined,3,4
    o1.f.apply(o2) // Shall display undefined,undefined,3,4
    
    o2.f.call(o1) // Shall display 1,2,undefined,undefined
    o2.f.apply(o1) // Shall display 1,2,undefined,undefined

    Le code ci-dessus montre clairement que la valeur «this» pour toute «fonction NON liée» peut être modifiée par appel / application . De plus, si le paramètre "this" n'est pas explicitement transmis à call / apply , "objet courant" (et donc la valeur de "this") est défini sur "window" en mode non strict et "undefined" en mode strict.

  4. A l'intérieur de la fonction "Bound Function" (c'est-à-dire une fonction qui a été liée par l'appel functionName.bind ):

    Une fonction liée est une fonction dont "cette" valeur a été fixée. Le code suivant montre comment "ceci" fonctionne en cas de fonction liée

    function UserDefinedFunction()
    {
        alert(this.a + ","  + this.b + ","  + this.c  + ","  + this.d)
    }
    var o1={
              a:1,
              b:2,
              f:UserDefinedFunction,
              bf:null
           }
    var o2={
               c:3,
               d:4,
               f:UserDefinedFunction,
               bf:null
            }
    
    var bound1=UserDefinedFunction.bind(o1); // permanantly fixes "this" value of function "bound1" to Object o1
    bound1() // Shall display 1,2,undefined,undefined
    
    var bound2=UserDefinedFunction.bind(o2); // permanantly fixes "this" value of function "bound2" to Object o2
    bound2() // Shall display undefined,undefined,3,4
    
    var bound3=o1.f.bind(o2); // permanantly fixes "this" value of function "bound3" to Object o2
    bound3() // Shall display undefined,undefined,3,4
    
    var bound4=o2.f.bind(o1); // permanantly fixes "this" value of function "bound4" to Object o1
    bound4() // Shall display 1,2,undefined,undefined
    
    o1.bf=UserDefinedFunction.bind(o2) // permanantly fixes "this" value of function "o1.bf" to Object o2
    o1.bf() // Shall display undefined,undefined,3,4
    
    o2.bf=UserDefinedFunction.bind(o1) // permanantly fixes "this" value of function "o2.bf" to Object o1
    o2.bf() // Shall display 1,2,undefined,undefined
    
    bound1.call(o2) // Shall still display 1,2,undefined,undefined. "call" cannot alter the value of "this" for bound function
    
    bound1.apply(o2) // Shall still display 1,2,undefined,undefined. "apply" cannot alter the value of "this" for bound function
    
    o2.bf.call(o2) // Shall still display 1,2,undefined,undefined. "call" cannot alter the value of "this" for bound function
    o2.bf.apply(o2) // Shall still display 1,2,undefined,undefined."apply" cannot alter the value of "this" for bound function

    Comme indiqué dans le code ci-dessus, "cette" valeur pour toute "fonction liée" NE PEUT PAS être modifiée par appel / application . De plus, si le "this" paramètre n'est pas explicitement transmis pour la liaison, "object courant" (et donc la valeur de "this" ) est défini sur "window" en mode Non strict et "undefined" en mode strict. Encore une chose. La liaison d'une fonction déjà liée ne modifie pas la valeur de "this" . Il reste défini comme la valeur définie par la première fonction de liaison.

  5. Alors que la création d'objets à travers "nouveau" :

    À l'intérieur d'une fonction constructeur, l ' "objet actuel" (et donc la valeur de "this" ) fait référence à l'objet qui est en cours de création via "new" quel que soit l'état de liaison de la fonction. Cependant, si le constructeur est une fonction liée, il doit être appelé avec un ensemble d'arguments prédéfini comme défini pour la fonction liée.

  6. Dans le gestionnaire d'événements Inline DOM :

    Veuillez consulter l'extrait HTML suivant

    <button onclick='this.style.color=white'>Hello World</button>
    <div style='width:100px;height:100px;' onclick='OnDivClick(event,this)'>Hello World</div>

    Le "ceci" dans les exemples ci-dessus fait respectivement référence à l'élément "bouton" et à l'élément "div".

    Dans le premier exemple, la couleur de police du bouton doit être définie sur blanc lorsque vous cliquez dessus.

    Dans le deuxième exemple, lorsque l' élément "div" est cliqué, il doit appeler la fonction OnDivClick avec son deuxième paramètre référençant l'élément div cliqué. Cependant, la valeur de "this" dans OnDivClick NE DOIT PAS faire référence à l' élément div cliqué . Il doit être défini comme «objet fenêtre» ou «non défini» dans les modes non strict et strict respectivement (si OnDivClick est une fonction non liée ) ou défini sur une valeur liée prédéfinie (si OnDivClick est une fonction liée )

Ce qui suit résume l'intégralité de l'article

  1. Dans le contexte global, "this" fait toujours référence à l' objet "window"

  2. Chaque fois qu'une fonction est invoquée, elle est invoquée dans le contexte d'un objet ( "objet courant" ). Si l' objet actuel n'est pas explicitement fourni, l' objet actuel est "l'objet fenêtre" en mode NON strict et "non défini" en mode strict par défaut.

  3. La valeur de "this" dans une fonction Non Bound est la référence à l'objet dans le contexte duquel la fonction est invoquée ( "objet courant" )

  4. La valeur de "ceci" dans une fonction non liée peut être remplacée par appel et appliquer des méthodes de la fonction.

  5. La valeur de "this" est fixée pour une fonction Bound et ne peut pas être remplacée par l' appel et l' application méthodes de la fonction.

  6. La fonction de liaison et déjà liée ne change pas la valeur de "this". Il reste défini comme la valeur définie par la première fonction de liaison.

  7. La valeur de "this" dans un constructeur est l'objet qui est créé et initialisé

  8. La valeur de "this" dans un gestionnaire d'événements DOM en ligne fait référence à l'élément pour lequel le gestionnaire d'événements est donné.

Arup Hore
la source
9

L'article probablement le plus détaillé et le plus complet thisest le suivant:

Explication douce de «ce» mot-clé en JavaScript

L'idée derrière thisest de comprendre que les types d'invocation de fonctions ont une importance significative sur la définition de la thisvaleur.


Lorsque vous avez des problèmes d'identification this, ne vous demandez pas:

Où est thispris à partir ?

mais ne demandez-vous:

Comment la fonction est-elle invoquée ?

Pour une fonction flèche (cas particulier de transparence du contexte), demandez-vous:

Quelle valeur a thisoù la fonction flèche est définie ?

Cet état d'esprit est correct lorsqu'il s'agit de thiset vous évitera des maux de tête.

Dmitri Pavlutin
la source
En plus de créer un lien vers votre blog, vous pourriez peut-être approfondir un peu la façon dont poser ces questions aide quelqu'un à comprendre le thismot clé.
Magnus Lind Oxlund
7

C'est la meilleure explication que je l' ai vu: Comprendre JavaScripts ce avec clarté

Le présent référence toujours fait référence à (et maintient la valeur de) un objet d' un objet et singulier , il est généralement utilisé à l' intérieur d' une fonction ou d' une méthode, bien qu'il puisse être utilisé en dehors d' une fonction dans la portée globale. Notez que lorsque nous utilisons le mode strict, cela contient la valeur d'undefined dans les fonctions globales et dans les fonctions anonymes qui ne sont liées à aucun objet.

Il y a quatre scénarios où cela peut être déroutant:

  1. Quand on passe une méthode (qui utilise ce ) comme argument à utiliser en fonction de rappel.
  2. Lorsque nous utilisons une fonction interne (une fermeture). Il est important de prendre note que les fermetures ne peuvent pas accéder à la fonction extérieure est cette variable de en utilisant le mot-clé this car la variable this n'est accessible que par la fonction elle-même, pas par les fonctions internes.
  3. Quand une méthode qui repose sur cette est affectée à une variable dans tous les contextes, dans ce cas , ces références un autre objet que prévu à l' origine.
  4. Lorsque vous utilisez ce ainsi que la liaison, appliquer et méthodes d'appel.

Il donne des exemples de code, des explications et des solutions, ce qui m'a semblé très utile.

James Drinkard
la source
6

En termes pseudoclassiques, la façon dont de nombreuses conférences enseignent le mot-clé «this» est comme un objet instancié par une classe ou un constructeur d'objet. Chaque fois qu'un nouvel objet est construit à partir d'une classe, imaginez que sous le capot, une instance locale d'un «ce» objet est créée et renvoyée. Je me souviens qu'il a enseigné comme ceci:

function Car(make, model, year) {
var this = {}; // under the hood, so to speak
this.make = make;
this.model = model;
this.year = year;
return this; // under the hood
}

var mycar = new Car('Eagle', 'Talon TSi', 1993);
// ========= under the hood
var this = {};
this.make = 'Eagle';
this.model = 'Talon TSi';
this.year = 1993;
return this;
mrmaclean89
la source
5

thisest l'un des concepts mal compris en JavaScript car il se comporte peu différemment d'un endroit à l'autre. Se thisréfère simplement au "propriétaire" de la fonction que nous exécutons actuellement .

thisaide à obtenir l'objet actuel (aka contexte d'exécution) avec lequel nous travaillons. Si vous comprenez dans quel objet la fonction en cours est CHAISE, vous pouvez comprendre ce que facilement en cours thisest -

var val = "window.val"

var obj = {
    val: "obj.val",
    innerMethod: function () {
        var val = "obj.val.inner",
            func = function () {
                var self = this;
                return self.val;
            };

        return func;
    },
    outerMethod: function(){
        return this.val;
    }
};

//This actually gets executed inside window object 
console.log(obj.innerMethod()()); //returns window.val

//Breakdown in to 2 lines explains this in detail
var _inn = obj.innerMethod();
console.log(_inn()); //returns window.val

console.log(obj.outerMethod()); //returns obj.val

Ci-dessus, nous créons 3 variables avec le même nom 'val'. Un dans le contexte global, un à l'intérieur de obj et l'autre à l'intérieur de la méthode d'obj. JavaScript résout les identifiants dans un contexte particulier en remontant la chaîne de portée du local au global.


Peu d'endroits où thisse différencier

Appel d'une méthode d'un objet

var status = 1;
var helper = {
    status : 2,
    getStatus: function () {
        return this.status;
    }
};

var theStatus1 = helper.getStatus(); //line1
console.log(theStatus1); //2

var theStatus2 = helper.getStatus;
console.log(theStatus2()); //1

Lorsque la ligne1 est exécutée, JavaScript établit un contexte d'exécution (EC) pour l'appel de fonction, en définissant thisl' objet référencé par ce qui précède le dernier "." . donc dans la dernière ligne, vous pouvez comprendre que cela a a()été exécuté dans le contexte global qui est le window.

Avec constructeur

this peut être utilisé pour faire référence à l'objet en cours de création

function Person(name){
    this.personName = name;
    this.sayHello = function(){
        return "Hello " + this.personName;
    }
}

var person1 = new Person('Scott');
console.log(person1.sayHello()); //Hello Scott

var person2 = new Person('Hugh');
var sayHelloP2 = person2.sayHello;
console.log(sayHelloP2()); //Hello undefined

Lorsque new Person()est exécuté, un objet entièrement nouveau est créé. Personest appelé et son thisest défini pour référencer ce nouvel objet.

Appel de fonction

function testFunc() {
    this.name = "Name";
    this.myCustomAttribute = "Custom Attribute";
    return this;
}

var whatIsThis = testFunc();
console.log(whatIsThis); //window

var whatIsThis2 = new testFunc();
console.log(whatIsThis2);  //testFunc() / object

console.log(window.myCustomAttribute); //Custom Attribute 

Si nous oublions un newmot-clé, fait whatIsThisréférence au contexte le plus global qu'il peut trouver ( window)

Avec des gestionnaires d'événements

Si le gestionnaire d'événements est en ligne, thisfait référence à un objet global

<script type="application/javascript">
    function click_handler() {
        alert(this); // alerts the window object
    }
</script>

<button id='thebutton' onclick='click_handler()'>Click me!</button>

Lors de l'ajout d'un gestionnaire d'événements via JavaScript, thisfait référence à l'élément DOM qui a généré l'événement.


Nipuna
la source
5

La valeur de "this" dépend du "contexte" dans lequel la fonction est exécutée. Le contexte peut être n'importe quel objet ou l'objet global, c'est-à-dire une fenêtre.

La sémantique de "ceci" est donc différente des langages OOP traditionnels. Et cela pose des problèmes: 1. lorsqu'une fonction est passée à une autre variable (très probablement, un rappel); et 2. lorsqu'une fermeture est invoquée à partir d'une méthode membre d'une classe.

Dans les deux cas, il s'agit de window.

Trombe
la source
3

Cette aide serait- elle utile? (La plus grande confusion de `` ceci '' en javascript vient du fait qu'il n'est généralement pas lié à votre objet, mais à la portée d'exécution actuelle - ce n'est peut-être pas exactement comment cela fonctionne, mais c'est toujours comme ça pour moi - voir l'article pour une explication complète)

Simon Groenewolt
la source
1
Il vaudrait mieux dire qu'il est lié " au contexte d'exécution actuel ". Sauf que ES6 (brouillon) change cela avec les fonctions fléchées, où cela est résolu dans le contexte d'exécution externe.
RobG
3

Quelques informations à ce sujet mot clé

Connectons le thismot-clé à la console dans la portée globale sans plus de code mais

console.log(this)

Dans le mot-clé Client / Navigateur this est un objet global qui estwindow

console.log(this === window) // true

et

Dans le mot de passe d' exécution Server / Node / Javascript this est également un objet global qui estmodule.exports

console.log(this === module.exports) // true
console.log(this === exports) // true

Gardez à l'esprit exportsest juste une référence àmodule.exports

unclexo
la source
1

cette utilisation pour Scope comme ça

  <script type="text/javascript" language="javascript">
$('#tbleName tbody tr').each(function{
var txt='';
txt += $(this).find("td").eq(0).text();
\\same as above but synatx different
var txt1='';
 txt1+=$('#tbleName tbody tr').eq(0).text();
alert(txt1)
});
</script>

la valeur de txt1 et txt est identique dans l'exemple ci-dessus $ (this) = $ ('# tbleName tbody tr') is Same

PRADEEP SINGH Chundawat
la source
1

J'ai une vision différente this des autres réponses qui, je l'espère, est utile.

Une façon de regarder JavaScript est de voir qu'il n'y a qu'une seule façon d'appeler une fonction 1 . C'est

functionObject.call(objectForThis, arg0, arg1, arg2, ...);

Il y a toujours une certaine valeur fournie pour objectForThis.

Tout le reste est du sucre syntaxique pour functionObject.call

Ainsi, tout le reste peut être décrit par la façon dont il se traduit functionObject.call.

Si vous appelez simplement une fonction thisest alors "l'objet global" qui dans le navigateur est la fenêtre

function foo() {
  console.log(this);
}

foo();  // this is the window object

En d'autres termes,

foo();

a été effectivement traduit en

foo.call(window);

Notez que si vous utilisez le mode strict alors thisseraundefined

'use strict';

function foo() {
  console.log(this);
}

foo();  // this is the window object

ce qui signifie

En d'autres termes,

foo();

a été effectivement traduit en

foo.call(undefined);

En JavaScript, il existe des opérateurs comme +et -et *. Il y a aussi l'opérateur point qui est.

L' .opérateur, lorsqu'il est utilisé avec une fonction à droite et un objet à gauche, signifie effectivement "passer l'objet commethis pour fonctionner".

Exemple

const bar = {
  name: 'bar',
  foo() { 
    console.log(this); 
  },
};

bar.foo();  // this is bar

En d'autres termes se bar.foo()traduit parconst temp = bar.foo; temp.call(bar);

Notez que la façon dont la fonction a été créée n'a pas d'importance (principalement ...). Tous ces éléments produiront les mêmes résultats

const bar = {
  name: 'bar',
  fn1() { console.log(this); },
  fn2: function() { console.log(this); },
  fn3: otherFunction,
};

function otherFunction() { console.log(this) };

bar.fn1();  // this is bar
bar.fn2();  // this is bar
bar.fn3();  // this is bar

Encore une fois, ce ne sont que du sucre syntaxique pour

{ const temp = bar.fn1; temp.call(bar); }
{ const temp = bar.fn2; temp.call(bar); }
{ const temp = bar.fn3; temp.call(bar); }

Une autre ride est la chaîne prototype. Lorsque vous utilisez a.bJavaScript, regardez d' abord l'objet référencé directement par apour la propriété b. S'il bn'est pas trouvé sur l'objet, JavaScript cherchera dans le prototype de l'objet à rechercher b.

Il existe différentes façons de définir le prototype d'un objet, la plus courante en 2019 est le classmot - clé. Pour les besoins de thiscela, cela n'a pas d'importance. Ce qui importe, c'est que lorsqu'il recherche dans l'objet aune propriété bs'il trouve une propriété bsur l'objet ou dans sa chaîne de prototypes s'il bfinit par être une fonction, les mêmes règles que ci-dessus s'appliquent. Les bréférences de fonction seront appelées en utilisant la callméthode et en passant acomme objectForThis comme indiqué en haut de cette réponse.

Maintenant. Imaginons que nous créons une fonction qui définit explicitement thisavant d'appeler une autre fonction, puis appelons-la avec l' .opérateur (point)

function foo() {
  console.log(this);
}

function bar() {
  const objectForThis = {name: 'moo'}
  foo.call(objectForThis);  // explicitly passing objectForThis
}

const obj = {
  bar,
};

obj.bar();  

Suite à la traduction à utiliser call, obj.bar()devient const temp = obj.bar; temp.call(obj);. Lorsque nous entrons dans la barfonction que nous appelons foomais que nous passons explicitement dans un autre objet pour objectForThis, donc quand nous arrivons à foo, thisc'est cet objet intérieur.

C'est ce que font à la fois bindet les =>fonctions. Ce sont des sucres plus syntaxiques. Ils construisent efficacement une nouvelle fonction invisible exactement comme barci-dessus qui définit explicitement thisavant d'appeler la fonction spécifiée. Dans le cas où bind thisest réglé sur ce que vous passez bind.

function foo() {
  console.log(this);
}

const bar = foo.bind({name: 'moo'});

// bind created a new invisible function that calls foo with the bound object.

bar();  

// the objectForThis we are passing to bar here is ignored because
// the invisible function that bind created will call foo with with
// the object we bound above

bar.call({name: 'other'});

Notez que s'il functionObject.bindn'existait pas, nous pourrions faire le nôtre comme ça

function bind(fn, objectForThis) {
  return function(...args) {
    return fn.call(objectForthis, ...args);
  };
}

et nous pourrions l'appeler comme ça

function foo() {
  console.log(this);
}

const bar = bind(foo, {name:'abc'});

Fonctions fléchées, l' =>opérateur est le sucre syntaxique pour la liaison

const a = () => {console.log(this)};

est le même que

const tempFn = function() {console.log(this)}; 
const a = tempFn.bind(this);

Tout comme bind, une nouvelle fonction invisible est créée qui appelle la fonction donnée avec une valeur liée objectForThismais contrairement à bindl'objet à lier, elle est implicite. C'est ce qui thisse passe quand l' =>opérateur est utilisé.

Donc, tout comme les règles ci-dessus

const a = () => { console.log(this); }  // this is the global object
'use strict';
const a = () => { console.log(this); }  // this is undefined
function foo() {
  return () => { console.log(this); }
}

const obj = {
  foo,
};
const b = obj.foo();
b();

obj.foo()se traduit par const temp = obj.foo; temp.call(obj);ce qui signifie que l'opérateur de flèche à l'intérieur foose liera objà une nouvelle fonction invisible et renverra cette nouvelle fonction invisible à laquelle il est affecté b. b()fonctionnera comme il a toujours comme b.call(window)ou en b.call(undefined)appelant la nouvelle fonction invisible qui a foocréé. Cette fonction invisible ignore le thispassé en elle et passe objcomme objectForThis` à la fonction flèche.

Le code ci-dessus se traduit par

function foo() {
  function tempFn() {
    console.log(this);
  }
  return tempFn.bind(this);
}

const obj = {
  foo,
};
const b = obj.foo();
b.call(window or undefined if strict mode);

1apply est une autre fonction similaire àcall

functionName.apply(objectForThis, arrayOfArgs);

Mais à partir d'ES6 conceptuellement, vous pouvez même traduire cela en

functionName.call(objectForThis, ...arrayOfArgs);
gman
la source
0

Résumé thisJavascript:

  • La valeur de thisest déterminée par la façon dont la fonction n'est pas invoquée, où elle a été créée!
  • Habituellement, la valeur de thisest déterminée par l'objet qui est à gauche du point. ( windowdans l'espace mondial)
  • Dans les écouteurs d'événements, la valeur de this fait référence à l'élément DOM sur lequel l'événement a été appelé.
  • Lorsqu'une fonction est appelée avec le newmot - clé, la valeur de thisfait référence à l'objet nouvellement créé
  • Vous pouvez manipuler la valeur thisdes fonctions: call, apply,bind

Exemple:

let object = {
  prop1: function () {console.log(this);}
}

object.prop1();   // object is left of the dot, thus this is object

const myFunction = object.prop1 // We store the function in the variable myFunction

myFunction(); // Here we are in the global space
              // myFunction is a property on the global object
              // Therefore it logs the window object
              
             

Exemples d'écouteurs d'événements:

document.querySelector('.foo').addEventListener('click', function () {
  console.log(this);   // This refers to the DOM element the eventListener was invoked from
})


document.querySelector('.foo').addEventListener('click', () => {
  console.log(this);  // Tip, es6 arrow function don't have their own binding to the this v
})                    // Therefore this will log the global object
.foo:hover {
  color: red;
  cursor: pointer;
}
<div class="foo">click me</div>

Exemple de constructeur:

function Person (name) {
  this.name = name;
}

const me = new Person('Willem');
// When using the new keyword the this in the constructor function will refer to the newly created object

console.log(me.name); 
// Therefore, the name property was placed on the object created with new keyword.

Willem van der Veen
la source
0

Pour bien comprendre "cela", il faut comprendre le contexte, la portée et la différence entre eux.

Portée : En javascript, la portée est liée à la visibilité des variables, la portée est obtenue grâce à l'utilisation de la fonction. (En savoir plus sur la portée)

Contexte : le contexte est lié aux objets. Il fait référence à l'objet auquel appartient une fonction. Lorsque vous utilisez le mot clé JavaScript «this», il fait référence à l'objet auquel appartient la fonction. Par exemple, à l'intérieur d'une fonction, lorsque vous dites: «this.accoutNumber», vous faites référence à la propriété «accoutNumber», qui appartient à l'objet auquel appartient cette fonction.

Si l'objet «myObj» a une méthode appelée «getMyName», lorsque le mot clé JavaScript «this» est utilisé à l'intérieur de «getMyName», il fait référence à «myObj». Si la fonction «getMyName» a été exécutée dans la portée globale, «this» fait référence à l'objet window (sauf en mode strict).

Voyons maintenant un exemple:

    <script>
        console.log('What is this: '+this);
        console.log(this);
    </script>

Runnig abobve code dans la sortie du navigateur: entrez la description de l'image ici

Selon la sortie que vous êtes à l'intérieur du contexte de l'objet fenêtre, il est également visible que le prototype de fenêtre se réfère à l'objet.

Essayons maintenant à l'intérieur d'une fonction:

    <script>
        function myFunc(){
            console.log('What is this: '+this);
            console.log(this);
        }
        myFunc();
    </script>

Production:

entrez la description de l'image ici La sortie est la même parce que nous avons enregistré «cette» variable dans la portée globale et nous l'avons enregistrée dans la portée fonctionnelle, nous n'avons pas changé le contexte. Dans les deux cas, le contexte était le même, lié à l' objet veuve .

Créons maintenant notre propre objet. En javascript, vous pouvez créer un objet de plusieurs façons.

 <script>
        var firstName = "Nora";
        var lastName = "Zaman";
        var myObj = {
            firstName:"Lord",
            lastName:'Baron',
            printNameGetContext:function(){
                console.log(firstName + " "+lastName);
                console.log(this.firstName +" "+this.lastName);
                return this;
            }
        }

      var context = myObj.printNameGetContext();
      console.log(context);
    </script>

Production: entrez la description de l'image ici

Ainsi, à partir de l'exemple ci-dessus, nous avons constaté que «ce» mot-clé fait référence à un nouveau contexte lié à myObj, et myObject a également une chaîne de prototype vers Object.

Allons jeter un autre exemple:

<body>
    <button class="btn">Click Me</button>
    <script>
        function printMe(){
            //Terminal2: this function declared inside window context so this function belongs to the window object.
            console.log(this);
        }
        document.querySelector('.btn').addEventListener('click', function(){
            //Terminal1: button context, this callback function belongs to DOM element 
            console.log(this);
            printMe();
        })
    </script>
</body>

sortie: est-ce logique? (lire les commentaires) entrez la description de l'image ici

Si vous avez du mal à comprendre l'exemple ci-dessus, essayons avec notre propre rappel;

<script>
        var myObj = {
            firstName:"Lord",
            lastName:'Baron',
            printName:function(callback1, callback2){
                //Attaching callback1 with this myObj context
                this.callback1 = callback1;
                this.callback1(this.firstName +" "+this.lastName)
                //We did not attached callback2 with myObj so, it's reamin with window context by default
                callback2();
                /*
                 //test bellow codes
                 this.callback2 = callback2;
                 this.callback2();
                */
            }
        }
        var callback2 = function (){
            console.log(this);
        }
        myObj.printName(function(data){
            console.log(data);
            console.log(this);
        }, callback2);
    </script>

production: entrez la description de l'image ici

Maintenant, comprenons la portée, le soi, l'IIFE et CECI comment se comporte

       var color = 'red'; // property of window
       var obj = {
           color:'blue', // property of window
           printColor: function(){ // property of obj, attached with obj
               var self = this;
               console.log('In printColor -- this.color: '+this.color);
               console.log('In printColor -- self.color: '+self.color);
               (function(){ // decleard inside of printColor but not property of object, it will executed on window context.
                    console.log(this)
                    console.log('In IIFE -- this.color: '+this.color);
                    console.log('In IIFE -- self.color: '+self.color); 
               })();

               function nestedFunc(){// decleard inside of printColor but not property of object, it will executed on window context.
                    console.log('nested fun -- this.color: '+this.color);
                    console.log('nested fun -- self.color: '+self.color);
               }

               nestedFunc(); // executed on window context
               return nestedFunc;
           }
       };

       obj.printColor()(); // returned function executed on window context
   </script> 

La sortie est assez impressionnante non? entrez la description de l'image ici

Seigneur
la source
-1

Réponse simple:

"ce" mot-clé dépend toujours du contexte d'invocation. Ils sont mentionnés ci-dessous.

  1. LA FONCTION EST APPELÉE AVEC UN NOUVEAU MOT-CLÉ

    Si la fonction est appelée avec un mot clé NEW, THIS sera liée à l'objet nouvellement créé.

    function Car(){
      this.name="BMW";
    }
    const myCar=new Car();
    myCar.name; // output "BMW"

    Dans ce qui précède, cela sera lié à l'objet 'myCar'

  2. LA FONCTION EST APPELÉE EXPLICITEMENT À L'AIDE D'APPELS ET DE MÉTHODES D'APPLICATION.

    Dans ce cas, CECI sera lié à l'objet qui est explicitement transmis à la fonction.

    var obj1={"name":"bond"};
    function printMessage(msg){
        return msg+" "+this.name;
    }
    const message=printMessage.call(obj1,"my name is ");
    console.log(message); //HERE THIS WILL BE BOUND TO obj1 WHICH WE PASSED EXPLICITLY. SAME FOR APPLY METHOD ALSO.
  3. SI LA FONCTION EST APPELÉE IMPLICITEMENT, CELA SERA LIÉ À CET OBJET

    var obj1={
       "name":"bond",
        getName: function () {
                    return this.name;
                 }
    };
    const newname=obj1.getName();
    console.log(newname); //HERE THIS WILL BE BOUND TO obj1(WHITCHEVER OBJECT IS MENTIONED BEFORE THE DOT THIS WILL BE BOUND TO THAT)
  4. QUAND LA FONCTION EST APPELÉE SANS AUCUN CONTEXTE, CELA SERA LIÉ À UN OBJET MONDIAL

    const util = {
       name: 'Utility',
       getName: function () {
                    return this.name;
    };
    
    const getName=util.getName;
    const newName=getName();
    console.log(newName); // IF THIS EXECUTED IN BROWSER THIS WILL BE  BOUND TO WINDOW OBJECT. IF THIS EXECUTED IN SERVER THIS WILL BE BOUND TO GLOBAL OBJECT
  5. EN MODE STRICT, CELA SERA INDÉFINI

    function setName(name){
        "use strict"
        return this.name;
    }
    setName(); //WILL BE ERROR SAYING name IS UNDEFINED. 
PALLAMOLLA SAI
la source