Comment fonctionne le mot-clé «this»?

Jun 27 2010

J'ai remarqué qu'il ne semble pas y avoir d'explication claire de ce qu'est le thismot-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 lui et je n'ai pas compris pourquoi cela s'est produit.

Comment ça thismarche et quand faut-il l'utiliser?

Réponses

1378 DanielTrebbien Jun 27 2010 at 20:15

Je recommande la lecture de Mike West article de Scope en JavaScript ( miroir ) en premier. C'est une excellente introduction conviviale aux concepts thiset 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 gère lorsqu'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:

1. Contexte d'exécution global initial

C'est le cas du code JavaScript qui est évalué au plus haut niveau, par exemple 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 mis à l'objet global, window( §10.4.1.1 ).

2. 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 mis à l'objet global comme s'il s'exécutait dans le contexte initial d'exécution globale ( §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) ('this') vs eval ('this') en JavaScript? et ECMA-262-5 de Dmitry Soshnikov en détail. Chapitre 2. Mode strict. pour quand vous pourriez utiliser un eval()appel indirect .

3. 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"](), alors ThisBinding est mis à 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 d'écrire «dans la plupart des autres cas» est qu'il existe huit fonctions intégrées ECMAScript 5 qui permettent à ThisBinding d'être spécifié dans la liste d'arguments. Ces fonctions spéciales prennent un soi-disant thisArgqui devient le 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 prend la valeur thisArg.

Dans le cas des Array.prototypefonctions, le donné callbackfnest appelé dans un contexte d'exécution où ThisBinding est mis à thisArgs'il est fourni; sinon, à l'objet global.

Telles sont les règles du JavaScript brut. 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 elles ont 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 thisvous passez des fonctions de rappel faisant référence à des fonctions de bibliothèque, vous devez vous référer à la documentation pour toute garantie 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 un fichier thisArg. Vous aussi, vous pouvez écrire votre propre fonction en prenant 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 de constructeur, la valeur de thisest le nouvel objet que l'interpréteur a créé:

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 Arrow 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 de flèche, this... se réfèrent aux valeurs de thisdans l'environnement dans lequel la fonction de 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?
    }
  1. Quelle est la valeur de thisà la ligne marquée quand obj.staticFunction()est exécuté? 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);
  

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

window

Dans cet exemple, l'interpréteur JavaScript entre le code de fonction, mais comme 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 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);
  

  1. 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.

 <!-- no snippet because, seemingly, eval doesn’t work in snippets -->

    function myFun() {
        return this; // What is `this` here?
    }
    var obj = {
        myMethod: function () {
            eval("myFun()");
        }
    };
  1. 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);
  

168 Mahesha999 Jul 08 2013 at 00:32

Le thismot-clé se comporte différemment en JavaScript par rapport aux autres langages. 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'appel de function ( context.function()) et par 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 puisque 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 windowobjet comme suit:

function f()
{
    return this;
}

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

2. Lorsqu'il est utilisé dans 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. C'est pour faire remarquer 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, qui thispointe toujours 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 d'une fonction sans contexte

Lorsque vous utilisez une thisfonction interne qui est appelé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. Cependant, il existe quelques différences.

  • Ci-dessus, nous avons ajouté des membres aux objets en utilisant la notation littérale d'objet. Nous pouvons ajouter des membres aux fonctions en utilisant this. pour les spécifier.
  • La notation littérale d'objet crée une instance d'objet que nous pouvons utiliser immédiatement. Avec la fonction, nous pouvons avoir besoin de créer d'abord son instance à l'aide de l' newopérateur.
  • Également dans une approche littérale d'objet, nous pouvons ajouter explicitement des membres à un objet déjà défini à l'aide de 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 soit reflétée dans toutes les instances de la fonction.

Ci-dessous, j'ai essayé toutes les choses que nous avons faites avec Object et thisau - 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é à l'intérieur de 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 à l'intérieur 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 de la fonction définie sur la chaîne prototype

Si la méthode est sur la chaîne de prototypes d'un objet, à l' thisintérieur de cette méthode fait référence à l'objet sur lequel 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 acceptent également tous les paramètres à passer à la fonction d'origine lorsqu'elle est appelée.
  • fun.apply(obj1 [, argsArray])Définit obj1comme valeur de thisinside fun()et appelle fun()des éléments de passage argsArraycomme ses arguments.
  • fun.call(obj1 [, arg1 [, arg2 [,arg3 [, ...]]]])- Définit obj1la valeur de thisinside fun()et les appels fun()passant arg1, arg2, arg3, ...comme ses arguments.
  • fun.bind(obj1 [, arg1 [, arg2 [,arg3 [, ...]]]])- Renvoie la référence à la fonction funavec thisfun lié à l'intérieur obj1et les paramètres de funliés aux paramètres spécifiés arg1, arg2, arg3,....
  • Maintenant la différence entre apply, callet binddevait se manifester. 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 d'entier non négatives correspondantes. Alors que callpermet de spécifier directement les arguments de la fonction. Both applyand callappelle immédiatement la fonction dans le contexte spécifié et avec les arguments spécifiés. D'autre part, 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'attribuant à 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 attribuez 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 une addeventListenerméthode ou par les méthodes traditionnelles d'enregistrement d'événements comme onclick.
  • De même, lorsque vous utilisez thisdirectement à l'intérieur de la propriété event (like <button onclick="...this..." >) de l'élément, cela 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 d'événements ou de la propriété d'événement résout 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 de modèle d'inscription d'événements de Microsoft attachEvent. Au lieu d'affecter la fonction au gestionnaire d'événements (et de faire ainsi la méthode de fonction de l'élément), il appelle la fonction sur l'événement (l'appelant effectivement dans un 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 de 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 de flèche est définie, sera la fonction de 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 
66 user3459110 Oct 26 2014 at 22:07

Javascript est 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 comme 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 tel que 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 l'un ou l'autre des environnements. Ceci est fait pour éviter les confusions en mode strict. thisserait, dans ce cas, simplement enregistrer undefined, car c'est ce que c'est, il n'est pas défini.

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

Appeler 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 devriez déjà savoir que la thisvariable dans ce cas fait référence au Objectsur lequel vous avez appelé cette fonction (notez qu'en javascript, à peu près tout est an Object, y compris Arrays et Functions). Prenez le code suivant par exemple.

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

Si an Objectcontient une propriété qui contient a 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 celle à 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 communément 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érez 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? Eh bien, 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 de Person.
  2. Le constructeur de this Objecta son constructeur défini sur Person. Notez également que cela typeof awalne reviendrait Objectque.
  3. Ce nouveau Objectserait assigné au 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 appelé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 de tels 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 comme tels, et nous les appelons donc uniquement comme tels.

Appel de fonctions sur les fonctions: calletapply

Alors oui, puisque les functions sont aussi Objects(et en fait des variables de première classe en Javascript), même les fonctions ont des méthodes qui sont ... enfin, des 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 thisdans la fonction foocomme une référence à thisArg. Tous les autres paramètres passés à callsont passés à la fonction en footant qu'arguments.
Ainsi, le code ci-dessus se connectera {myObj: "is cool"}, [1, 2, 3]à la console. Jolie façon de changer la valeur de thisdans n'importe quelle fonction.

applyest presque identique à 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' thisappel 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 aussi 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 applysera en fait appeler la fonction. bind, d'autre part, renvoie 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]`

Vous voyez la différence entre les trois? C'est subtil, mais ils sont utilisés différemment. Comme callet apply, bindremplacera également la valeur de thisset par l'invocation de la méthode par points.

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

Trucs supplémentaires, copiez ceci

Parfois, vous n'aimez pas le fait que les thischangements 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 thisde la portée d'origine. Nous avons donc « copié » thisà thatet utilisé la copie au lieu de this. Intelligent, hein?

Indice:

  1. Qu'est-ce qui est retenu thispar défaut?
  2. Et si nous appelons la fonction comme une méthode avec la notation Object-dot?
  3. Et si nous utilisons le newmot-clé?
  4. Comment manipuler thisavec callet apply?
  5. Utilisation bind.
  6. Copie thispour résoudre les problèmes de portée imbriquée.
49 arunjitsingh Jun 27 2010 at 21:10

"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 des valeurs en elle-même en utilisant "this". La POO 101 enseigne que «ceci» n'est applicable 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 «this» dans des fonctions de fermeture anonymes comme:

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

Donc ici, à l'intérieur de chaque (), "this" ne contient pas la "valeur" que 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 = ceci; // petite monnaie
    self.value = valeur;
    $ ('. some-elements'). each (function (elt) {
        elt.innerHTML = self.value; // phew!! == 2
    });
}) (2);

Essaye le; vous commencerez à aimer ce modèle de programmation

18 carlodurso Oct 30 2014 at 10:58

Depuis que ce fil de discussion a augmenté, j'ai compilé quelques points pour les lecteurs thisnovices.

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

Nous utilisons cela de la même manière que nous utilisons les pronoms dans des langues naturelles comme l'anglais: "John court vite parce qu'il essaie de prendre 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 jusqu'à ce qu'un objet appelle 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 .

Quand use strict, thisdans les fonctions globales et anonymes qui ne sont liées à aucun objet détient la valeur undefined.

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

Ce qui réserve l'avenir

Définies dans ECMA Script 6 , les fonctions fléchées adoptent la thisliaison de la portée 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 fournissent une alternative à l'utilisation bind(), il est important de noter qu'elles désactivent essentiellement le thismécanisme traditionnel en faveur d'une portée lexicale plus largement comprise. (1)


Les 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
18 Seph Oct 07 2013 at 02:46

thisen JavaScript se réfère toujours 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 window, est référencé.

Donc si je l'ai fait

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 faites simplement référence à la fonction, pas la remise à l'élément. Par conséquent, thisfera référence à l'objet window.

15 blockhead Jun 27 2010 at 20:15

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

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

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

Par défaut, et ce qui déroute la plupart des débutants, lorsqu'un auditeur 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 ce changement trivial avec jQuery.proxy.

11 ArmanMcHitarian Apr 23 2013 at 19:57

Daniel, super explication! Quelques mots à ce sujet et une bonne liste de thispointeurs de contexte d'exécution dans le cas de gestionnaires d'événements.

En deux mots, thisen JavaScript pointe l'objet à partir duquel (ou à partir du contexte d'exécution duquel) la fonction actuelle a été exécutée et il est toujours en lecture seule, vous ne pouvez pas le 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 précédemment et avant, alors soyez prudent et il est préférable de rester à l'écart de 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)">
11 zangw Nov 29 2015 at 13:01

Voici une bonne source de thisin JavaScript.

Voici le résumé:

  • global ce

    Dans un navigateur, au niveau global, 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 le premier espace de noms. 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, thisà la 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 ça

Sauf dans le cas des gestionnaires d'événements DOM ou quand a thisArgest fourni (voir plus bas), à la fois dans le nœud et dans un navigateur en 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;, dans quel 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, elle 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 ceci

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 affectées à la prototypepropriété. Vous accédez à ces valeurs en utilisant 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 []
  • objectez ceci

Vous pouvez utiliser thisdans n'importe quelle fonction sur un objet pour faire référence à d'autres propriétés sur 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 HTML DOM, thisest toujours une référence à l'élément DOM auquel l'événement était 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 y 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 ceci

le jQuery se thisréférera à de nombreux endroits à 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>
9 ArupHore Jan 31 2017 at 15:29

Il y a beaucoup de confusion quant à la façon dont "ce" mot-clé est interprété en JavaScript. Espérons que cet article permettra à tous de se reposer une fois pour toutes. Et beaucoup plus. Veuillez lire attentivement l'intégralité de l'article. Soyez prévenu 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 l' un des 6 suivants:

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

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 "ceci" ) est toujours l' objet "fenêtre" pour les navigateurs.

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

    À l'intérieur d'un appel direct de «fonction non liée», l'objet qui a appelé l'appel de fonction devient «l'objet courant» (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 / invoquer cette fonction directement via "UserDefinedFunction ()" l'appellera / l'invoquera automatiquement comme "window.UserDefinedFunction ()" faisant "window" comme "objet courant" (et donc la valeur de " this " ) dans " UserDefinedFunction " .L'invocation de cette fonction en" Mode non strict "entraînera les résultats suivants

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

    En "Strict Mode", appeler / appeler la fonction directement via "UserDefinedFunction ()" "ne sera " PAS " automatiquement appeler / invoquer comme " window.UserDefinedFunction () ". Par conséquent, " l'objet courant " (et la valeur de " this " ) dans "UserDefinedFunction" ne doit pas être défini . L'appel de cette fonction en "Mode strict" entraînera les résultats suivants

    UserDefinedFunction() // displays undefined
    

    Cependant, l'invoquer explicitement en utilisant un objet window entraînera le résultat suivant

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

    Regardons 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'affiche. Les valeurs de "c" et "d" ont été affichées comme non définies car o1 ne définit pas ces propriétés

    De même , lorsque « UserDefinedFunction » a été invoqué par o2 , « cette » prend valeur de o2 et la valeur de ses propriétés « c » et « d » obtenir affichée.Procédé valeur de « a » et « b » ont été présentés comme non défini comme o2 ne pas définir ces propriétés.

  3. À l'intérieur de l'appel indirect "Fonction non liée" via functionName.call et functionName.apply :

    Lorsqu'une "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 du paramètre "this" (premier paramètre) passé à call / 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 Bound" peut être modifiée via call / apply . De plus, si le paramètre «this» n'est pas explicitement passé à call / apply , «current object» (et donc la valeur de «this») est défini sur «window» en mode non strict et «undefined» en mode strict.

  4. Dans l'appel "Bound Function" (c'est-à-dire une fonction qui a été liée en appelant functionName.bind ):

    Une fonction liée est une fonction dont la valeur "this" a été fixée. Le code suivant a montré 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 paramètre "this" n'est pas explicitement passé à bind, "current object" (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 change pas la valeur de "this" . Il reste défini comme la valeur définie par la première fonction de liaison.

  5. Lors de la création d'objets via "nouveau" :

    Dans une fonction constructeur, l ' "objet courant" (et donc la valeur de "this" ) fait référence à l'objet qui est actuellement créé via "nouveau", 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. Gestionnaire d'événements à l'intérieur du DOM en ligne :

    Veuillez consulter l'extrait de code 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 "this" dans les exemples ci-dessus se réfère respectivement à l'élément "button" et à l'élément "div".

    Dans le premier exemple, la couleur de police du bouton doit être définie sur blanc lorsque l'utilisateur clique 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 tout l'article

  1. Dans le contexte global, "ceci" fait toujours référence à l' objet "fenêtre"

  2. Chaque fois qu'une fonction est invoquée, elle est invoquée dans le contexte d'un objet ( "objet courant" ). Si l' objet courant n'est pas explicitement fourni, l' objet courant 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 liée est la référence à l'objet dans le contexte duquel la fonction est appelée ( "objet courant" )

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

  5. La valeur de "this" est fixe pour une fonction liée et ne peut pas être remplacée par les méthodes d' appel et d' application 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é.

9 DmitriPavlutin Nov 08 2016 at 19:17

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

Explication douce du mot-clé "this" en JavaScript

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


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

Où est thispris à partir ?

mais ne demandez-vous:

Comment la fonction est-elle appelée ?

Pour une fonction de flèche (cas particulier de la transparence du contexte) posez-vous la question:

Quelle valeur a thislà où la fonction de flèche est définie ?

Cet état d'esprit est correct lors du traitement thiset vous évitera des maux de tête.

7 JamesDrinkard Jul 13 2016 at 02:03

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

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

Il existe quatre scénarios où cela peut prêter à confusion:

  1. Lorsque nous transmettons une méthode (qui utilise ceci ) comme argument à utiliser comme fonction de rappel.
  2. Lorsque nous utilisons une fonction interne (une fermeture). Il est important de noter que les fermetures ne peuvent pas accéder à la variable this de la fonction externe 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. Lorsqu'une méthode qui repose sur cela est affectée à une variable dans différents contextes, auquel cas cela fait référence à un autre objet que celui initialement prévu.
  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 que j'ai trouvé très utile.

6 Nipuna Aug 09 2014 at 16:22

thisest l'un des concepts mal compris en JavaScript car il se comporte peu différemment d'un endroit à l'autre. Simplement, thisfait référence au "propriétaire" de la fonction que nous exécutons actuellement .

thisaide à obtenir l'objet courant (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 un contexte global, un à l'intérieur de obj et l'autre à l'intérieur de innerMethod de 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

Appeler 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 line1 est exécuté, JavaScript établit un contexte d'exécution (EC) pour l'appel de fonction, définissant thisl' objet référencé par tout 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 complètement nouveau est créé. Personest appelé et il 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 manquons le newmot-clé, fait whatIsThisréférence au contexte le plus global qu'il peut trouver ( window)

Avec les 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.


  • Vous pouvez également manipuler le contexte en utilisant .apply() .call()et.bind()
  • Le proxy JQuery est un autre moyen que vous pouvez utiliser pour vous assurer que cela dans une fonction sera la valeur que vous désirez. (Vérifiez Comprendre l'utilisation de $ .proxy () , jQuery.proxy () )
  • Que var that = thissignifie en JavaScript
6 mrmaclean89 Sep 17 2017 at 05:11

En termes pseudoclassiques, la façon dont de nombreuses conférences enseignent le mot-clé «this» est comme un objet instancié par un constructeur de classe ou d'objet. Chaque fois qu'un nouvel objet est construit à partir d'une classe, imaginez que sous le capot, une instance locale d'un objet «this» 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;
5 Trombe Jul 03 2017 at 17:07

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.

Ainsi, la sémantique de «ceci» est 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 appelée à partir d'une méthode membre d'une classe.

Dans les deux cas, il est défini sur window.

4 SimonGroenewolt Jun 27 2010 at 20:15

Qu'est- ce que cela peut aider? (La plupart de la 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)

3 unclexo Jul 25 2018 at 14:04

Un peu d'informations sur ce mot clé

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

console.log(this)

Dans Client / Browser, le this mot clé est un objet global qui estwindow

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

et

Dans Server / Node / Javascript runtime, le this mot clé est également un objet global qui estmodule.exports

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

Gardez à l'esprit que ce exportsn'est qu'une référence àmodule.exports

1 PRADEEPSINGHChundawat Apr 06 2016 at 14:15

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 la même dans l'exemple ci-dessus $ (this) = $ ('# tbleName tbody tr') est identique

1 gman Jan 29 2019 at 01:37

J'ai une vision différente thisdes autres réponses qui, je l'espère, sont utiles.

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

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

Il y a toujours une valeur fournie pour objectForThis.

Tout le reste est du sucre syntaxique pour functionObject.call

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

Si vous appelez simplement une fonction, alors thisest "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 en fait «passer l'objet thisà la fonction».

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 peu importe comment la fonction a été créée (principalement ...). Tout cela produira 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, commencez par rechercher l'objet référencé directement par ala propriété b. Si l'objet bn'est pas trouvé, JavaScript cherchera dans le prototype de l'objet pour trouver b.

Il existe différentes manières de définir le prototype d'un objet, la plus courante en 2019 est le classmot - clé. Pour les besoins, thiscela n'a pas d'importance. Ce qui compte, c'est que lorsqu'il recherche dans l'objet la apropriété bs'il trouve une propriété bsur l'objet ou dans sa chaîne de prototype 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.

À présent. Imaginons que nous fassions une fonction qui définit explicitement thisavant d'appeler une autre fonction, puis que nous l'appelions 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 un autre objet pour objectForThis, lorsque nous arrivons à foo, thisc'est cet objet interne.

C'est ce que les deux bindet =>fonctions font efficacement. Ce sont des sucres plus syntaxiques. Ils construisent effectivement une nouvelle fonction invisible exactement comme barci-dessus qui définit explicitement thisavant d'appeler la fonction spécifiée. Dans le cas de bind, il thisest défini sur tout ce à quoi 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 créer le nôtre comme ça

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

et alors nous pourrions l'appeler comme ça

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

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

Fonctions fléchées, les =>opérateurs sont des sucres syntaxiques pour bind

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 pour objectForThismais contrairement à bindl'objet à lier est implicite. C'est tout ce qui thisse passe lorsque 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()traduit 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 est assignée b. b()fonctionnera comme il l'a toujours fait b.call(window)ou en b.call(undefined)appelant la nouvelle fonction invisible foocréée. Cette fonction invisible ignore le qui y est thispassé et passe objcomme objectForThis` à la fonction de 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);
WillemvanderVeen Aug 22 2018 at 00:12

Résumé thisJavascript:

  • La valeur de thisest déterminée par la façon dont la fonction n'est pas appelée, où elle a été créée!
  • Habituellement, la valeur de thisest déterminée par l'objet qui se trouve à gauche du point. ( windowdans l'espace mondial)
  • Dans les écouteurs d'événements, la valeur de thisfait référence à l'élément DOM sur lequel l'événement a été appelé.
  • Lorsque in function est appelé 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
              
             

Exemple 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.

Lord May 20 2020 at 16:43

Pour bien comprendre «ceci», 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 atteint 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, alors «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>

Exécuter le code abobve dans la sortie du navigateur:

Selon la sortie que vous êtes à l'intérieur du contexte de l'objet window, il est également visible que le prototype de fenêtre fait référence à 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:

La sortie est la même car 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 manières.

 <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:

Ainsi, à partir de l'exemple ci-dessus, nous avons constaté que le mot-clé «this» fait référence à un nouveau contexte lié à myObj, et que myObject a également une chaîne 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: Ça a du sens, non? (lire les commentaires)

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:

Comprenons maintenant Scope, Self, 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 géniale, non?