Maison  >  Questions et réponses  >  le corps du texte

Comprendre la fonction et l'utilisation appropriée du mot-clé « this »

J'espérais trouver une explication claire de ce que fait le mot-clé "this" et comment l'utiliser correctement.

Il semble se comporter étrangement et je ne comprends pas vraiment pourquoi.

thisComment ça marche et quand faut-il l'utiliser ?

P粉155551728P粉155551728373 Il y a quelques jours541

répondre à tous(2)je répondrai

  • P粉087951442

    P粉0879514422023-10-13 14:03:41

    Par rapport à d'autres langues, this 关键字在 JavaScript 中的行为有所不同。在面向对象语言中,this 关键字指的是该类的当前实例。在 JavaScript 中,this 的值由函数的调用上下文 (context.function()) et sa position d'appel sont déterminées.

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

    Quand on l'utilise dans un contexte global this 时,它会绑定到全局对象(浏览器中的window)

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

    Lorsque vous utilisez this 时,this dans une fonction définie dans le contexte global, vous êtes toujours lié à l'objet global car la fonction est en fait une méthode du contexte global. < /p>

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

    Appelez-le sur l'objet f1是一个全局对象的方法。因此我们也可以在 window ci-dessus, comme ceci :

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

    <强>2. Lorsqu'il est utilisé dans une méthode objet

    Lorsque vous utilisez this 关键字时,this à l'intérieur d'une méthode objet, il se lie à l'objet "direct" englobant.

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

    J'ai mis le mot "immédiatement" entre guillemets ci-dessus. Cela montre que si un objet est imbriqué dans un autre objet, this est lié à l'objet 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 en tant que méthode à l'objet, elle suit toujours les règles ci-dessus, c'est-à-dire que this pointe toujours vers l'objet parent direct.

    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

    Utilisé this 时,它会绑定到全局对象(浏览器中的window) lorsque vous l'appelez dans une fonction sans aucun contexte (c'est-à-dire pas sur un objet) (même si la fonction est définie à l'intérieur d'un 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

    Essayez tout avec les fonctions

    Nous pouvons également utiliser des fonctions pour essayer les points ci-dessus. Mais il existe encore quelques différences.

    • Ci-dessus, nous avons ajouté des membres à l'objet en utilisant la notation littérale d'objet. 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. Pour les fonctions, nous devrons peut-être d'abord en créer une instance à l'aide de l'opérateur new.
    • Également dans les méthodes littérales d'objet, nous pouvons ajouter explicitement des membres à l'objet défini à l'aide de l'opérateur point. Ceci n’est ajouté que dans des cas spécifiques. Cependant, j'ai ajouté la variable au prototype de fonction afin qu'elle soit reflétée dans toutes les instances de la fonction.

    Ci-dessous, j'ai essayé tout ce que j'ai fait ci-dessus avec Object et this mais j'ai d'abord créé la fonction au lieu d'écrire directement l'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() + "
    "); //[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() + "
    "); //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() + "
    "); //v1 obj2.incrementVersion(); //incrementing version in obj2 //does not affect obj1 version document.write(obj2.getVersion() + "
    "); //v2 document.write(obj1.getVersion() + "
    "); //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() + "
    "); //[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()+"
    ");//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 d'un constructeur .

    Lorsqu'une fonction est utilisée comme constructeur (c'est-à-dire lorsqu'elle est appelée à l'aide du mot-clé new 关键字调用时),函数体内的 this), le < /p> dans le corps de la fonction 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é dans une fonction définie sur la chaîne prototype

    🎜

    Si la méthode se trouve sur la chaîne de prototypes de l'objet, alors this au sein de la méthode fait référence à l'objet sur lequel la méthode est appelée, comme si la méthode était définie sur cet 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 seule fois et de l'appeler dans différents contextes. Autrement dit, ils permettent de préciser la valeur this qui sera utilisée lors de l'exécution de la fonction. Ils peuvent également transmettre n'importe quel argument à la fonction d'origine lors de son appel.
    • fun.apply(obj1 [, argsArray])obj1 设置为 this 内的值code>fun() 并调用 fun(),传递 argsArrayfun.apply(obj1 [, argsArray])
    • Définissez
    • obj1 sur la valeur contenue dans code>fun() et appelez fun.call(obj1 [, arg1 [, arg2 [,arg3 [, ...]]]]) - 设置 obj1 作为 fun()this 的值,并调用 fun()fun() , en passant des éléments de argsArray comme arguments. < /code>
    • fun.call(obj1 [, arg1 [, arg2 [,arg3 [, ...]]]]) fun.bind(obj1 [, arg1 [, arg2 [,arg3 [, ...]]]]) - 返回对函数的引用fun,其中 fun 内的 this 绑定到 obj1,并且 fun 的参数绑定到指定的参数 arg1、arg2, arg3,... - Définit obj1 comme
    • fun() à l'intérieur de
    • value et appelle applycallbind 之间的区别一定已经很明显了。 apply 允许将参数指定为类似数组的对象,即具有数字 length 属性和相应的非负整数属性的对象。而 call 允许直接指定函数的参数。 applycallfun() en passant
    • arg1, arg2, arg3, ...
    comme arguments.

    thisfun.bind(obj1 [, arg1 [, arg2 [,arg3 [, ...]]]])

    - Renvoie une référence à la fonction fun, où fun is Le 🎜 est lié à 🎜obj1, et les arguments de 🎜fun sont liés aux arguments spécifiés 🎜arg1, arg2, arg3,.... 🎜 🎜Maintenant, la différence entre 🎜apply, 🎜call et 🎜bind doit être évidente. 🎜apply permet de spécifier des arguments sous forme d'objets de type tableau, c'est-à-dire des objets avec une propriété numérique 🎜length et une propriété entière non négative correspondante. Et 🎜call permet de spécifier directement les paramètres de la fonction. 🎜apply et 🎜call appellent immédiatement la fonction dans le contexte spécifié et avec les paramètres spécifiés. bind, d'autre part, renvoie simplement la fonction liée à la valeur et aux arguments spécifiés. Nous pouvons capturer une référence à cette fonction renvoyée en l'attribuant à une variable, que nous pouvons ensuite appeler à tout moment. 🎜 🎜
    function add(inc1, inc2)
    {
        return this.a + inc1 + inc2;
    }
    
    var o = { a : 4 };
    document.write(add.call(o, 5, 6)+"
    "); //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]) + "
    "); //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()+"
    "); //15 var h = add.bind(o, 5); //h: `o.a` i.e. 4 + 5 + ? document.write(h(6) + "
    "); //15 // 4 + 5 + 6 = 15 document.write(h() + "
    "); //NaN //no parameter is passed to h() //thus inc2 inside add() is `undefined` //4 + 5 + undefined = NaN
    🎜🎜7. 🎜🎜🎜 à l'intérieur du gestionnaire d'événements
    • Lorsque vous attribuez une fonction directement au gestionnaire d'événements d'un élément, cela se fait à l'aide de méthodes traditionnelles d'enregistrement d'événements telles que this 来引用相应的元素。这种直接的函数分配可以使用 addeventListener 方法或通过 onclick directement dans la fonction de gestionnaire d'événements.
    • De même, lorsque vous appelez directement l'attribut événement d'un élément comme
    • .
    • Cependant, this 会解析为全局对象 window est utilisé indirectement via d'autres fonctions appelées dans les gestionnaires d'événements ou les propriétés d'événements.
    • Le même comportement que ci-dessus peut être obtenu lorsque nous utilisons l'approche du modèle d'enregistrement d'événements de Microsoft attachEvent pour attacher une fonction à un gestionnaire d'événements. Au lieu d'attribuer une fonction à un gestionnaire d'événement (créant ainsi une méthode fonction de l'élément), il appelle la fonction sur l'événement (l'appelant effectivement dans le contexte global).

    Je recommande JSFiddle.

    sssccc
    
    

    Using `this` "directly" inside event handler or event property



    Using `this` "indirectly" inside event handler or event property



    IE only:

    <强>8. this

    dans les fonctions fléchées ES6

    Dans une fonction flèche, this 的行为类似于公共变量:它将从其词法范围继承。定义箭头函数的函数的 this 将是箭头函数的 this se comporte comme une variable publique : elle sera héritée de sa portée lexicale. Le

    de la fonction qui définit la fonction flèche sera le

    de la fonction flèche.

    C'est donc le même comportement que :

    (function(){}).bind(this)
    🎜Voir le code ci-dessous : 🎜
    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 
    

    répondre
    0
  • P粉156532706

    P粉1565327062023-10-13 11:53:32

    est un mot-clé en JavaScript qui est un attribut du contexte d'exécution. Son utilisation principale est dans les fonctions et les constructeurs. this Les règles sont assez simples (si vous respectez les bonnes pratiques).

    Description techniquethis dans le cahier des charges

    Standard ECMAScriptdéfinitionthis via des opérations abstraites (en abrégé AO) ResolveThisBinding :

    Les

    Enregistrements d'environnement globaux, Enregistrements d'environnement de module et Enregistrements d'environnement de fonction ont chacun leur propre méthode GetThisBinding.

    GetThisEnvironment AO recherche le LexicalEnvironment du contexte d'exécution en cours actuel et trouve l'enregistrement d'environnement ascendant le plus proche (en itérant sur sa propriété [[OuterEnv]]) qui a une liaison this< /em> (c'est-à-dire que HasThisBinding renvoie true ) . Le processus se termine par l'un des trois types d'enregistrement d'environnement.

    La valeur de

    this dépend généralement du fait que le code soit en mode strict.

    La valeur de retour de

    GetThisBinding reflète la valeur this 值,因此每当建立新的执行上下文时,this du contexte d'exécution actuel, donc chaque fois qu'un nouveau contexte d'exécution est établi,

    sera résolu en une valeur différente. Cela peut également se produire lorsque le contexte d'exécution actuel est modifié. Les sous-sections suivantes répertorient cinq scénarios dans lesquels cela pourrait se produire.

    Vous pouvez placer des échantillons de code dans AST Explorer

    pour suivre les détails des spécifications.

    1. Contexte d'exécution global dans les scripts

    Il s'agit d'un code de script qui est évalué au niveau supérieur, par exemple directement dans .

    thisDans le contexte d'exécution global initial du script, l'évaluation de amène GetThisBinding

    à suivre les étapes suivantes : 🎜

    La propriété [[GlobalThisValue]] de l'enregistrement d'environnement global est toujours définie sur l'objet global défini par l'hôte, accessible via globalThisglobalThis ( Web 上的 window,Node.js 上的 global ( fenêtre sur le Web , Node.js global ; Documentation sur MDN). Suivez les étapes de InitializeHostDefinedRealm pour savoir comment la propriété [[GlobalThisValue]] est générée.

    2. Contexte d'exécution global dans module

    Les modules ont été introduits dans ECMAScript 2015.

    Cela fonctionne pour les modules, par exemple directement à l'intérieur