Cum funcționează cuvântul cheie „this”? (Programare, Javascript, Acest)

Maxim Gershkovich a intrebat.

Am observat că nu pare să existe o explicație clară a ceea ce înseamnă cuvântul this cuvântul cheie și cum este folosit corect (și incorect) în JavaScript pe site-ul Stack Overflow.

Am fost martor la un comportament foarte ciudat cu acesta și nu am reușit să înțeleg de ce s-a produs.

Cum funcționează this funcționează și când ar trebui să fie utilizat?

Comentarii

21 răspunsuri

Vă recomandăm să citiți Mike West‘s article Domeniul de aplicare în JavaScript (oglindă) mai întâi. Acesta este o introducere excelentă și prietenoasă în conceptele de this și de lanțuri de domeniu de aplicare în JavaScript.

Odată ce începeți să vă obișnuiți cu this, regulile sunt de fapt destul de simple. ECMAScript 5.1 Standard definește this:

§11.1.1 this cuvânt cheie

this se evaluează la valoarea lui ThisBinding din contextul de execuție curent.

ThisBinding este ceva ce interpretul JavaScript păstrează pe măsură ce evaluează codul JavaScript, ca un registru special al procesorului care conține o referință la un obiect. Interpretul actualizează ThisBinding ori de câte ori stabilește un context de execuție într-unul dintre cele trei cazuri diferite:

1. Contextul de execuție global inițial

Acesta este cazul codului JavaScript care este evaluat la nivel superior, de exemplu, atunci când se află direct în interiorul unui fișier <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>

Atunci când se evaluează codul în contextul inițial de execuție globală, ThisBinding este setat la obiectul global, window (§10.4.1.1).

2. Introducerea codului de evaluare

  • …printr-un apel direct la eval()ThisBinding rămâne neschimbată; este aceeași valoare ca și ThisBinding a contextului de execuție apelant (§10.4.2 (2)(a)).

  • …dacă nu este un apel direct la eval()
    ThisBinding este setat la valoarea obiectului global ca și cum se execută în contextul inițial de execuție globală (§10.4.2 (1)).

§15.1.2.2.1.1 definește ce înseamnă un apel direct la eval() este. În esență, eval(...) este un apel direct, în timp ce ceva de genul (0, eval)(...) sau var indirectEval = eval; indirectEval(...); este un apel indirect la eval(). A se vedea răspunsul lui chuckj la (1, eval)(‘this’) vs eval(‘this’) în JavaScript? și ECMA-262-5 al lui Dmitry Soshnikov în detaliu. Capitolul 2. Modul strict. pentru situațiile în care puteți utiliza o metodă indirectă eval() apel indirect.

3. Introducerea codului de funcție

Acest lucru apare atunci când se apelează o funcție. În cazul în care o funcție este apelată pe un obiect, cum ar fi în obj.myMethod() sau echivalentul obj["myMethod"](), atunci ThisBinding este setat la obiectul (obj în exemplu; §13.2.1). În majoritatea celorlalte cazuri, ThisBinding este setat la obiectul global (§10.4.3).

Motivul pentru care am scris „în majoritatea celorlalte cazuri” este acela că există opt funcții încorporate în ECMAScript 5 care permit ca ThisBinding să fie specificat în lista de argumente. Aceste funcții speciale iau un așa-numit thisArg care devine ThisBinding la apelarea funcției (§10.4.3).

Aceste funcții speciale încorporate sunt:

  • 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 ] )

În cazul funcției Function.prototype acestea sunt apelate pe un obiect funcție, dar în loc să seteze ThisBinding la obiectul funcție, ThisBinding este setat la thisArg.

În cazul funcțiilor Array.prototype funcțiile, obiectul dat callbackfn este apelată într-un context de execuție în care ThisBinding este setat la thisArg în cazul în care este furnizat; în caz contrar, la obiectul global.

Acestea sunt regulile pentru JavaScript simplu. Atunci când începeți să utilizați biblioteci JavaScript (de exemplu, jQuery), este posibil să constatați că anumite funcții de bibliotecă manipulează valoarea lui this. Dezvoltatorii acelor biblioteci JavaScript fac acest lucru deoarece tinde să susțină cele mai frecvente cazuri de utilizare, iar utilizatorii bibliotecii consideră de obicei că acest comportament este mai convenabil. Atunci când treceți funcții de callback care fac referire la this către funcțiile de bibliotecă, trebuie să consultați documentația pentru orice garanție cu privire la valoarea lui this este atunci când funcția este apelată.

Dacă vă întrebați cum manipulează o bibliotecă JavaScript valoarea lui this, biblioteca utilizează pur și simplu una dintre funcțiile JavaScript încorporate care acceptă un parametru thisArg. Și dumneavoastră puteți să vă scrieți propria funcție care acceptă o funcție de callback și thisArg:

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

Există un caz special pe care nu l-am menționat încă. Atunci când se construiește un obiect nou prin intermediul funcției new interpretorul JavaScript creează un obiect nou, gol, stabilește unele proprietăți interne și apoi apelează funcția de construcție a noului obiect. Astfel, atunci când o funcție este apelată într-un context de constructor, valoarea lui this este noul obiect creat de interpretor:

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);

Funcții săgeată

Funcții săgeată (introduse în ECMA6) modifică domeniul de aplicare al this. A se vedea întrebarea canonică existentă, Funcția Arrow vs declarația de funcție / expresii: Sunt ele echivalente / interschimbabile? pentru mai multe informații. Dar, pe scurt:

Funcțiile săgeată nu au propriile lor this…. binding.În schimb, acești identificatori sunt rezolvați în domeniul lexical ca orice altă variabilă. Asta înseamnă că în interiorul unei funcții săgeată, this…se referă la valorile lui this în mediul în care este definită funcția săgeată.

Doar pentru a vă distra, testați-vă înțelegerea cu câteva exemple

Pentru a descoperi răspunsurile, treceți cu mouse-ul peste căsuțele gri deschis.

  1. Care este valoarea lui this la linia marcată? De ce?

window – Linia marcată este evaluată în contextul inițial de execuție globală.

    if (true) {
        // What is `this` here?
    }
  1. Care este valoarea lui this la linia marcată atunci când obj.staticFunction() este executată? De ce?

obj – Atunci când se apelează o funcție pe un obiect, ThisBinding este setat la obiect.

  1. Care este valoarea lui this la linia marcată? De ce?

window

În acest exemplu, interpretul JavaScript introduce codul funcției, dar deoarece myFun/obj.myMethod nu este apelat pe un obiect, ThisBinding este setat la valoarea window.

Acest lucru este diferit de Python, în care accesarea unei metode (obj.myMethod) creează un obiect de metodă legat.

  1. Care este valoarea lui this la linia marcată? De ce?

window

Aceasta a fost dificilă. La evaluarea codului de evaluare, this este obj. Cu toate acestea, în codul de evaluare, myFun nu este apelat pe un obiect, astfel încât ThisBinding este setat la window pentru apel.

 <!-- 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. Care este valoarea lui this la linia marcată? De ce?

obj

Linia myFun.call(obj); invocă funcția încorporată specială Function.prototype.call(), care acceptă thisArg ca prim argument.

Comentarii

  • @Ali: Acestea sunt referințe la secțiuni din cadrul ediției 5.1 a standardului ECMAScript, ECMA-262. Le furnizez pentru ca tu să poți citi Standardul pentru detalii tehnice dacă dorești. –  > Por Daniel Trebbien.
  • Cred că @supertonsky are dreptate în legătură cu nr. 2 – dacă myFun() este apelat din domeniul global, și nu ca o metodă pe obiect, „this” va fi obiectul global, deci formularea întrebării contează. btw – I într-adevăr îmi place foarte mult ideea de a folosi mouseover pentru a obține răspunsul pentru așa ceva. –  > Por user655489.
  • Dar, jsfiddle.net/H4LYm/2 arată că setTimeout exemplu are un this de window(global). –  > Por Kevin Meredith.
  • venind de la Python, vă puteți imagina nivelul de frustrare pe care l-am avut când am dat peste al treilea exemplu… smh –  > Por Marius Mucenicu.
  • Probabil că acest răspuns ar trebui actualizat pentru a reflecta realitatea ES2020, chiar dacă schimbările sunt doar terminologice. –  > Por Ben Aston.
Mahesha999

The this se comportă diferit în JavaScript în comparație cu alte limbaje. În limbajele orientate pe obiecte, cuvântul this se referă la instanța curentă a clasei. În JavaScript, valoarea lui this este determinată de contextul de invocare a funcției (context.function()) și locul în care este apelată.

1. Atunci când este utilizat în context global

Atunci când se utilizează this în context global, aceasta este legată de obiectul global (window în browser)

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

Atunci când se utilizează this în interiorul unei funcții definite în context global, this este în continuare legat de obiectul global, deoarece funcția este de fapt transformată într-o metodă a contextului global.

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

Mai sus f1 este transformată într-o metodă a obiectului global. Prin urmare, o putem apela și pe window după cum urmează:

function f()
{
    return this;
}

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

2. Atunci când se utilizează în interiorul unei metode de obiect

Atunci când se utilizează this în interiorul unei metode obiect, this este legat de obiectul „imediat” care îl înconjoară.

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

Mai sus am pus cuvântul „imediat” între ghilimele duble. Aceasta pentru a sublinia faptul că, în cazul în care obiectul este înglobat într-un alt obiect, atunci this este legat de părintele imediat.

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

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

Chiar dacă adăugați în mod explicit o funcție la obiect ca metodă, aceasta respectă în continuare regulile de mai sus, și anume this indică în continuare obiectul părinte imediat.

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. Atunci când se invocă o funcție fără context

Atunci când utilizați this în interiorul unei funcții care este invocată fără context (adică nu pe niciun obiect), aceasta este legată de obiectul global (window în browser)(chiar dacă funcția este definită în interiorul obiectului) .

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 

Încercați totul cu funcții

Putem încerca punctele de mai sus și cu funcții. Cu toate acestea, există câteva diferențe.

  • Mai sus am adăugat membri la obiecte folosind notarea literală a obiectului. Putem adăuga membri la funcții folosind this. pentru a le specifica.
  • Notarea literală a obiectului creează o instanță a obiectului pe care o putem utiliza imediat. În cazul funcțiilor, este posibil să fie necesar să creăm mai întâi instanța acestora folosind new operator.
  • De asemenea, într-o abordare literală a obiectului, putem adăuga în mod explicit membri la un obiect deja definit, utilizând operatorul punct. Aceștia sunt adăugați doar la instanța specifică. Cu toate acestea, am adăugat o variabilă la prototipul funcției, astfel încât aceasta să se reflecte în toate instanțele funcției.

Mai jos am încercat toate lucrurile pe care le-am făcut cu Object și this de mai sus, dar creând mai întâi o funcție în loc să scriu direct un obiect.

/********************************************************************* 
  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. Atunci când este utilizat în interiorul funcției constructor.

Atunci când funcția este utilizată ca un constructor (adică atunci când este apelată cu new cuvântul cheie), this în interiorul corpului funcției indică noul obiect care se construiește.

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. Atunci când se utilizează în interiorul funcției definite în lanțul prototipurilor

În cazul în care metoda se află în lanțul de prototipuri al unui obiect, this în interiorul unei astfel de metode se referă la obiectul pentru care a fost apelată metoda, ca și cum metoda ar fi definită pe obiect.

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. În interiorul funcțiilor call(), apply() și bind()

  • Toate aceste metode sunt definite pe Function.prototype.
  • Aceste metode permit scrierea unei funcții o singură dată și invocarea ei în contexte diferite. Cu alte cuvinte, ele permit să se specifice valoarea lui this care va fi utilizată în timpul executării funcției. De asemenea, ele acceptă orice parametru care va fi transmis funcției originale atunci când aceasta este invocată.
  • fun.apply(obj1 [, argsArray]) Seturi obj1 ca valoare a funcției this în interiorul fun() și apelează fun() trecând elementele din argsArray ca argumente.
  • fun.call(obj1 [, arg1 [, arg2 [,arg3 [, ...]]]]) – Seturi obj1 ca valoare a lui this în interiorul fun() și apelează fun() trecând arg1, arg2, arg3, ... ca argumente.
  • fun.bind(obj1 [, arg1 [, arg2 [,arg3 [, ...]]]]) – Returnează referința la funcția fun cu this în interiorul funcției legate la obj1 și parametrii de fun legată de parametrii specificați arg1, arg2, arg3,....
  • Până acum, diferența dintre apply, call și bind trebuie să fi devenit evidentă. apply permite specificarea argumentelor funcției ca obiect de tip array, adică un obiect cu un număr length și proprietățile numerelor întregi nenegative corespunzătoare. În timp ce call permite specificarea directă a argumentelor pentru funcție. Ambele apply și call invocă imediat funcția în contextul specificat și cu argumentele specificate. Pe de altă parte, bind returnează pur și simplu funcția legată de contextul specificat this valoarea și argumentele specificate. Putem capta referința la această funcție returnată prin atribuirea ei unei variabile și, ulterior, o putem apela oricând.
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

7. this În interiorul gestionarilor de evenimente

  • Atunci când atribuiți o funcție direct la gestionarii de evenimente ai unui element, se utilizează funcția this direct în interiorul funcției de tratare a evenimentelor se referă la elementul corespunzător. O astfel de alocare directă a funcțiilor se poate face utilizând addeventListener sau prin intermediul metodelor tradiționale de înregistrare a evenimentelor, cum ar fi onclick.
  • În mod similar, atunci când utilizați this direct în interiorul proprietății evenimentului (cum ar fi <button onclick="...this..." >) a elementului, aceasta se referă la elementul respectiv.
  • Cu toate acestea, utilizarea lui this indirectă prin intermediul altei funcții apelate în interiorul funcției de tratare a evenimentului sau a proprietății evenimentului se rezolvă la obiectul global window.
  • Același comportament de mai sus se obține atunci când atașăm funcția la gestionarul de evenimente folosind metoda modelului de înregistrare a evenimentelor Microsoft attachEvent. În loc să se atribuie funcția gestionarului de evenimente (și astfel să se transforme în metoda de funcție a elementului), se apelează funcția la eveniment (apelând-o efectiv în context global).

Vă recomand să încercați mai bine acest lucru în 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. this în ES6 funcția arrow

Într-o funcție săgeată, this se va comporta ca și variabilele comune: va fi moștenită din domeniul său lexical. Funcția thisîn care este definită funcția săgeată, va fi funcția săgeată a lui this.

Așadar, acesta este același comportament ca și în cazul lui :

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

A se vedea următorul cod:

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 

Comentarii

  • „Atunci când utilizați această funcție în interiorul unei funcții definite în contextul global, aceasta este încă legată de obiectul global, deoarece funcția este de fapt transformată într-o metodă a contextului global.” este incorect. this este stabilit prin modul în care este apelată o funcție sau prin bind, nu de locul în care este definită. Apelarea oricărei funcții fără o referință de bază („context”) va fi implicită acest la obiectul global sau va rămâne nedefinită în modul strict. –  > Por RobG.
  • @RobG hmm poate fi, dar am găsit acest lucru pe MDN: În acest caz, valoarea lui this nu este setată de apel. Deoarece codul nu este în modul strict, valoarea lui this trebuie să fie întotdeauna un obiect, astfel încât valoarea implicită este cea a obiectului global. De fapt, de aceea am crezut că putem face direct apelul window.f1(), ceea ce înseamnă că f1() este deja atașat la window obiect, adică înainte de invocare. Am înțeles greșit? –  > Por Mahesha999.
  • Am comentat (poate că nu în mod clar) cu privire la legătura pe care ați făcut-o între setarea lui acestui cu „funcția este de fapt transformată într-o metodă a contextului global”, ca și cum ar fi un fel de a fi numit window.fn, ceea ce nu este așa. acest lucru este implicită la obiectul global deoarece nu a fost utilizată nicio referință de bază în apel, nu din cauza locului în care este definită funcția (deci this este încă setată de modul în care a fost apelată funcția). Dacă o apelați în mod explicit folosind window.fn, atunci setați acest lucru la fereastră. Același rezultat, un mod diferit de a proceda. 🙂 –  > Por RobG.
  • „mai sus am pus cuvântul imediat…” nu, nu ai făcut-o. Poți te rog să revizuiești acest text astfel încât eroarea să fie corectată? Mi se pare semantică față de răspuns și astfel nu pot continua să citesc până nu se repară eroarea de teamă să nu aflu ceva incorect. –  > Por TylerH.
  • @TylerH faceți Ctrl+F pe această pagină în browserul dvs. pentru a găsi șirul de caractere „immediate” (inclusiv ghilimelele duble) Cred că este acolo dacă vă înțeleg greșit – -.  > Por Mahesha999.
user3459110

Javascript’s this

Invocarea simplă a unei funcții

Luați în considerare următoarea funcție:

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

Rețineți că o executăm în modul normal, adică nu este utilizat modul strict.

Atunci când se execută într-un browser, valoarea lui this ar fi înregistrată ca window. Acest lucru se datorează faptului că window este variabila globală în domeniul de aplicare al unui browser web.

Dacă executați aceeași bucată de cod într-un mediu precum node.js, this se va referi la variabila globală din aplicația dvs.

Acum, dacă rulăm acest lucru în modul strict adăugând declarația "use strict"; la începutul declarației funcției, this nu se va mai referi la variabila globală în niciunul dintre medii. Acest lucru se face pentru a evita confuziile în modul strict. this ar fi, în acest caz, doar log undefined, pentru că asta este, nu este definită.

În cazurile următoare, am vedea cum se poate manipula valoarea lui this.

Apelarea unei funcții pe un obiect

Există diferite moduri de a face acest lucru. Dacă ați apelat metode native în Javascript, cum ar fi forEach și slice, ar trebui să știți deja că funcția this în acest caz se referă la variabila Object pe care ați apelat acea funcție (rețineți că în javascript, aproape totul este un Object, inclusiv Arrays și Functions). Să luăm ca exemplu următorul cod.

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

Dacă un Object conține o proprietate care deține un Function, proprietatea se numește metodă. Această metodă, atunci când este apelată, va avea întotdeauna this setată la valoarea Object cu care este asociată. Acest lucru este valabil atât pentru modul strict, cât și pentru cel non-strict.

Rețineți că, dacă o metodă este stocată (sau, mai degrabă, copiată) într-o altă variabilă, referința la this nu mai este păstrată în noua variabilă. De exemplu:

// continuing with the previous code snippet

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

Luând în considerare un scenariu mai frecvent practic:

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

new cuvânt cheie

Luați în considerare o funcție constructor în 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`

Cum funcționează aceasta? Ei bine, să vedem ce se întâmplă atunci când folosim new cuvântul cheie.

  1. Apelarea funcției cu ajutorul cuvântului new ar inițializa imediat un obiect Object de tip Person.
  2. Constructorul acestui Object are constructorul său setat la Person. De asemenea, rețineți că typeof awal ar returna Object numai.
  3. Acest nou Object ar fi atribuit prototipul lui Person.prototype. Acest lucru înseamnă că orice metodă sau proprietate din Person ar fi disponibilă pentru toate instanțele lui Person, inclusiv awal.
  4. Funcția Person însăși este acum invocată; this fiind o referință la obiectul nou construit awal.

Destul de simplu, nu?

Rețineți că specificația oficială ECMAScript nu afirmă nicăieri că astfel de tipuri de funcții sunt reale. constructor funcții. Acestea sunt doar funcții normale, iar new pot fi utilizate pentru orice funcție. Doar că noi le folosim ca atare și, prin urmare, le numim doar ca atare.

Apelarea funcțiilor asupra funcțiilor: call și apply

Deci da, din moment ce functions sunt, de asemenea, și Objects (și, de fapt, variabile de primă clasă în Javascript), chiar și funcțiile au metode care sunt… ei bine, funcții în sine.

Toate funcțiile moștenesc de la globalul Function, iar două dintre numeroasele sale metode sunt call și apply, și ambele pot fi folosite pentru a manipula valoarea lui this în funcția asupra căreia sunt apelate.

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

Acesta este un exemplu tipic de utilizare a funcției call. Practic, acesta ia primul parametru și stabilește this în funcție foo ca referință la thisArg. Toți ceilalți parametri trecuți către call este transmis la funcția foo ca argumente.
Astfel, codul de mai sus va înregistra {myObj: "is cool"}, [1, 2, 3] în consolă. O modalitate destul de frumoasă de a schimba valoarea lui this în orice funcție.

apply este aproape la fel ca call cu excepția faptului că acceptă doar doi parametri: thisArg și o matrice care conține argumentele care trebuie transmise funcției. Astfel, funcția de mai sus call poate fi tradus în apply în felul următor:

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

Rețineți că call și apply pot înlocui valoarea lui this stabilită prin invocarea metodei dot despre care am discutat în al doilea punct.Destul de simplu 🙂

Prezentând…. bind!

bind este un frate al lui call și apply. Este, de asemenea, o metodă moștenită de toate funcțiile din grupul global Function în Javascript. Diferența dintre bind și call/apply este că ambele call și apply vor invoca efectiv funcția. bindPe de altă parte, , pe de altă parte, returnează o nouă funcție cu thisArg și arguments prestabilite. Să luăm un exemplu pentru a înțelege mai bine acest lucru:

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]`

Vedeți diferența dintre cele trei? Este subtilă, dar ele sunt utilizate în mod diferit. Cum ar fi call și apply, bind va anula, de asemenea, valoarea lui this stabilită prin invocarea metodei cu puncte.

De asemenea, rețineți că niciuna dintre aceste trei funcții nu aduce nicio modificare funcției originale. call și apply ar returna valoarea din funcțiile proaspăt construite, în timp ce bind va returna însăși funcția proaspăt construită, gata să fie apelată.

În plus, copiați acest lucru

Uneori, nu vă place faptul că this se schimbă odată cu domeniul de aplicare, în special cu domeniul de aplicare imbricate. Aruncați o privire la următorul exemplu.

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"
        });
    }
  };

În codul de mai sus, vedem că valoarea lui this s-a schimbat odată cu domeniul de aplicare imbricate, dar noi am vrut ca valoarea lui this din domeniul de aplicare original. Așa că am „copiat this la that și am folosit copia în loc de this. Isteț, nu?

Index:

  1. Ce se află în this în mod implicit?
  2. Ce se întâmplă dacă apelăm funcția ca o metodă cu notația Object-dot?
  3. Ce se întâmplă dacă folosim new cuvânt cheie?
  4. Cum manipulăm this cu call și apply?
  5. Utilizarea bind.
  6. Copierea this pentru a rezolva problemele legate de sfera de cuprindere imbricate.

arunjitsingh

„this” se referă la domeniul de aplicare. Fiecare funcție are propriul domeniu de aplicare și, din moment ce totul în JS este un obiect, chiar și o funcție poate stoca unele valori în sine folosind „this”. OOP 101 ne învață că „this” se aplică numai la instanțelor unui obiect. Prin urmare, de fiecare dată când o funcție se execută, o nouă „instanță” a acelei funcții are o nouă semnificație a lui „this”.

Cei mai mulți oameni se încurcă atunci când încearcă să folosească „this” în interiorul unor funcții de închidere anonime, cum ar fi:

(function(value) {
    this.value = value;
    $('.some-elements').each(function(elt){
        elt.innerHTML = this.value;        // uh oh!! possibly undefined
    });
})(2);

Deci, aici, în interiorul each(), „this” nu deține „valoarea” pe care o așteptați (din

this.value = value;

de deasupra sa). Deci, pentru a depăși această problemă (fără joc de cuvinte), un dezvoltator ar putea:

(function(value) {
    var self = this;            // small change
    self.value = value;
    $('.some-elements').each(function(elt){
        elt.innerHTML = self.value;        // phew!! == 2 
    });
})(2);

Încercați; veți începe să vă placă acest model de programare.

Comentarii

  • „totul în JS este un obiect” nu este adevărat, JavaScript are și valori primitive, vezi bclary.com/2004/11/07/#a-4.3.2 –  > Por Marcel Korpel.
  • Valorile primitive par să aibă unele metode pe ele însele, cum ar fi String#substring(), Number#toString(), etc.. Deci, poate nu cu aceeași nomenclatură ca în articolul respectiv, ele se comportă într-adevăr ca și cum ar fi obiecte (toate sunt prototipate, adică String#substring() este într-adevăr: String.prototype.substring = function(){…}). Vă rog să mă corectați dacă mă înșel. –  > Por arunjitsingh.
  • this nu are nimic de-a face cu domeniul de aplicare. De asemenea, are o semnificație și în funcțiile care nu sunt proprietăți ale obiectelor. –  > Por Bergi.
  • @arunjitsingh-există două școli de gândire în această privință. Mie îmi place cea care spune „totul este un obiect, dar unele pot fi reprezentate prin primitive pentru comoditate„. 😉 –  > Por RobG.
  • this nu se referă în totalitate la domeniul de aplicare. Totul se referă la contextul de execuție, care nu este același lucru cu domeniul de aplicare. JavaScript are o sferă lexicală (ceea ce înseamnă că sfera de cuprindere este determinată de locația codului), dar this este determinat de modul în care este invocată funcția care îl conține – nu de locul în care se află acea funcție. –  > Por Scott Marcus.
carlodurso

Deoarece acest fir de discuție a revenit în actualitate, am compilat câteva puncte pentru cititorii noi în materie de this subiect.

Cum este valoarea this determinată?

Folosim acest lucru în mod similar cu modul în care folosim pronumele în limbile naturale, cum ar fi engleza: „John aleargă repede pentru că el încearcă să prindă trenul”. În schimb, am fi putut scrie „… John încearcă să prindă trenul”.

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 nu i se atribuie o valoare până când un obiect invocă funcția în care este definit. În domeniul global, toate variabilele globale și funcțiile globale sunt definite pe window obiect. Prin urmare, this într-o funcție globală se referă la (și are valoarea) obiectului global window obiect.

La use strict, this în funcțiile globale și în funcțiile anonime care nu sunt legate de niciun obiect deține o valoare de undefined.

Adresa this este cel mai prost înțeles când: 1) împrumutăm o metodă care folosește this, 2) atribuim o metodă care utilizează this la o variabilă, 3) o funcție care utilizează this este transmisă ca funcție de apelare și 4) this este utilizată în interiorul unei închideri – o funcție interioară. (2)

Ce deține viitorul

Definit în ECMA Script 6, funcțiile-săgeată adoptă standardul this din domeniul de cuprindere (funcție sau global) care se închide.

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!

În timp ce funcțiile săgeată oferă o alternativă la utilizarea bind()este important de reținut că, în esență, acestea dezactivează funcția tradițională this tradițional în favoarea unui domeniu de cuprindere lexical mai larg înțeles. (1)


Referințe:

  1. this & Prototipuri de obiecte, de Kyle Simpson. © 2014 Getify Solutions.
  2. javascriptissexy.com – http://goo.gl/pvl0GX
  3. Angus Croll – http://goo.gl/Z2RacU

Seph

this în JavaScript se referă întotdeauna la „proprietarul” funcției care este este executată.

În cazul în care nu este definit un proprietar explicit, atunci se face referire la cel mai înalt proprietar, adică la obiectul fereastră.

Deci, dacă am făcut

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

element.onclick = someKindOfFunction;

this s-ar referi la obiectul element. Dar aveți grijă, multă lume face această greșeală.

<element onclick="someKindOfFunction()">

În acest din urmă caz, nu faceți decât să faceți referire la funcție, nu să o predați elementului. Prin urmare, this se va referi la obiectul fereastră.

blockhead

Fiecare context de execuție în javascript are un this care este setat de:

  1. Modul în care este apelată funcția (inclusiv ca metodă obiect, utilizarea de call și apply, utilizarea lui new)
  2. Utilizarea de bind
  3. Din punct de vedere lexical pentru funcțiile săgeată (acestea adoptă stilul this din contextul lor de execuție exterior)
  4. Dacă codul este în mod strict sau non-strict
  5. Dacă codul a fost invocat utilizând eval

Puteți seta valoarea lui this utilizând func.call, func.apply sau func.bind.

În mod implicit, și ceea ce îi derutează pe cei mai mulți începători, atunci când un ascultător este apelat după ce un eveniment este generat pe un element DOM, se utilizează this a funcției este elementul DOM.

jQuery face ca acest lucru să fie ușor de schimbat cu jQuery.proxy.

Comentarii

  • Este un pic mai corect să spunem că fiecare funcție apelată are un domeniu de aplicare. Cu alte cuvinte, ceea ce este derutant la this în Javascript este faptul că este nu o proprietate intrinsecă a funcției în sine, ci mai degrabă un artefact al modului în care funcția este invocată. –  > Por Pointy.
  • @pointy mulțumiri. ceea ce provoacă cea mai mare confuzie cu privire la acest lucru în js este faptul că în toate limbajele folosite anterior (c#, c++), – acest lucru nu poate fi manipulat n întotdeauna punctează la instanța obiectului, în timp ce în js depinde și poate fi schimbat atunci când se invocă funcții folosind func.call, func.bind etc. – Sushil –  > Por Sushil.
  • this se ocupă de nu face referire la domeniul de aplicare al unei funcții. this va face referire la un anumit obiect (sau, eventual, la undefined), care, după cum ați spus, poate fi modificat folosind .call() sau .apply(). Domeniul unei funcții de o funcție este (în esență, atunci când este simplificată) la ce variabile are acces, iar acest lucru depinde în întregime de locul în care este declarată funcția și nu poate fi modificat. –  > Por nnnnnnnn.
  • @Pointy: „Este un pic mai corect să spunem că fiecare apel de funcție are un domeniu de aplicare.” Este chiar mai corect să spunem că funcțiile (și acum blocurile) au domeniu de aplicare, funcție apeluri de funcții au context. Domeniul de aplicare definește care sunt identificatorii care pot fi utilizați de codul din acel domeniu de aplicare. Contextul definește la ce sunt legați acești identificatori. –  > Por T.J. Crowder.
  • „Oricare ar fi acest domeniu de aplicare, se face referire la „this”.” Nu, this și domeniul de aplicare nu au nicio legătură între ele în ES5 și înainte (de exemplu, când a fost scris acest răspuns). În ES2015 (aka ES6), this și domeniul de aplicare sunt legate unul mod destul de minimalist în ceea ce privește funcțiile săgeată (funcția this dintr-o funcție săgeată este moștenită de la domeniul de cuprindere care o înconjoară), dar this nu se referă niciodată la un domeniu de aplicare. –  > Por T.J. Crowder.
Arman

Daniel, minunată explicație! Câteva cuvinte pe această temă și o listă bună de this pointer de context de execuție în cazul gestionarilor de evenimente.

În două cuvinte, this în JavaScript punctează obiectul de la care (sau din al cărui context de execuție) a fost rulată funcția curentă și este întotdeauna read-only, oricum nu îl poți seta (o astfel de încercare se va termina cu mesajul ‘Invalid left-hand side in assignment’.

Pentru gestionarii de evenimente: gestionarii de evenimente inline, cum ar fi <element onclick="foo">, suprascriu orice alți gestionari atașați mai devreme și înainte, așa că aveți grijă și este mai bine să nu folosiți deloc delegarea de evenimente în linie. și îi mulțumesc lui Zara Alaverdyan care m-a inspirat la această listă de exemple printr-o dezbatere în contradictoriu 🙂

  • 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)">

zangw

Aici este o sursă bună de this în JavaScript.

Iată rezumatul:

  • global acest

    Într-un browser, la nivel global, this este windowobiect

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

    În node utilizând repl, this este spațiul de nume de top. Vă puteți referi la el ca global.

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

    În node executarea dintr-un script, this la nivel global începe ca un obiect gol. Nu este același lucru cu global

    \test.js
    console.log(this);  \ {}
    console.log(this === global); \ fasle
    
  • funcția this

Cu excepția cazului gestionarilor de evenimente DOM sau atunci când o funcție thisArg este furnizat (a se vedea mai jos), atât în nod, cât și într-un browser care utilizează this într-o funcție care nu este apelată cu new face referire la domeniul global…

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

În cazul în care utilizați use strict;, caz în care this va fi undefined

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

Dacă apelați o funcție cu new this va fi un context nou, nu va face referire la contextul 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>
  • prototip this

Funcțiile pe care le creați devin obiecte funcție. Acestea primesc automat un caracter special prototype specială, căreia îi puteți atribui valori. Atunci când creați o instanță prin apelarea funcției dvs. cu new veți avea acces la valorile pe care le-ați atribuit proprietății prototype proprietății. Accesați aceste valori utilizând this.

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

Thing.prototype.foo = "bar";

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

De obicei, este o greșeală să atribuiți array-uri sau obiecte pe prototype. Dacă doriți ca fiecare instanță să aibă propriul său array, creați-l în funcție, nu în prototip.

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 []
  • obiect this

Puteți utiliza this în orice funcție a unui obiect pentru a face referire la alte proprietăți ale obiectului respectiv. Acest lucru nu este același lucru cu o instanță creată cu new.

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

obj.logFoo(); //logs "bar"
  • DOM event this

Într-un gestionar de evenimente DOM HTML, this este întotdeauna o referință la elementul DOM la care a fost atașat evenimentul.

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();

Cu excepția cazului în care bind contextul

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 this

În interiorul atributelor HTML în care puteți pune JavaScript, this este o referință la element.

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

Puteți utiliza eval pentru a accesa this.

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

var thing = new Thing();
thing.logFoo();
  • cu this

Puteți utiliza with pentru a adăuga this la domeniul de aplicare curent pentru a citi și a scrie la valorile de pe this fără a se referi la this în mod explicit.

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

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

jQuery va avea în multe locuri this să se refere la un element 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>

Arup Hore

Există o mulțime de confuzii în ceea ce privește modul în care „this” este interpretat cuvântul cheie în JavaScript. Să sperăm că acest articol le va lămuri pe toate odată pentru totdeauna. Și multe altele. Vă rugăm să citiți cu atenție întregul articol. Vă avertizăm că acest articol este lung.

Indiferent de contextul în care este folosit, „aceasta” se referă întotdeauna la „obiectul curent” în Javascript. Cu toate acestea, ceea ce trebuie să facă „obiect curent” este diferă în funcție de context. context poate fi exact 1 dintre cele 6 următoarele:

  1. Global (adică în afara tuturor funcțiilor)
  2. În interiorul unui apel direct la o „funcție nemijlocită”. (adică o funcție care are nu a fost legată prin apelarea functionName.bind)
  3. În interiorul apelului indirect la o „funcție nelegată”. prin numefuncție.call și functionName.apply
  4. Apelul în interiorul unei „funcții legate”. (adică o funcție care a fost legată prin apelarea functionName.bind)
  5. În timp ce crearea de obiecte prin „new”
  6. În interiorul gestionarului de evenimente DOM în linie

În cele ce urmează se descrie fiecare dintre aceste contexte, unul câte unul:

  1. Context global (adică în afara tuturor funcțiilor):

    În afara tuturor funcțiilor (adică în context global) „currentbject” (și, prin urmare, valoarea lui „this”) este întotdeauna„window” pentru browsere.

  2. În interiorul unui apel direct la o „funcție nemijlocită”:

    În interiorul unui apel direct la o „funcție nemijlocită”, obiectul care a invocat apelul de funcție devine „obiectul curent”. (și, prin urmare, valoarea lui „this”). În cazul în care o funcție este apelată fără un apel explicit obiect curent, se va folosi obiectul curent este fie „fereastră” (pentru modul non-strict) sau nedefinit (pentru modul strict) . Orice funcție (sau variabilă) definită încontext global devine automat o proprietate a obiectului „window” De exemplu, să presupunem că o funcție este definită în contextul global sub forma

    function UserDefinedFunction(){
        alert(this)
        }
    

    aceasta devine proprietatea obiectului „fereastră”, ca și cum ați fi definit-o ca

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

    În „Non Strict Mode”, apelarea/invocarea acestei funcții direct prin intermediul „UserDefinedFunction()” va fi apelată/invocată automat ca „window.UserDefinedFunction()” ceea ce face ca „window” ca fiind„obiect curent” (și, prin urmare, valoarea lui „this”) în cadrul „UserDefinedFunction”Invocarea acestei funcții în „Non Strict Mode” va avea următorul rezultat

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

    În „Strict Mode”, apelarea/invocarea directă a funcției prin intermediul funcției„UserDefinedFunction()” va fi „NU” o va apela/invoca automat ca fiind „window.UserDefinedFunction()”De aici rezultă că „currentbject” (și valoarea lui „this”) din„UserDefinedFunction” trebuie să fie nedefinită. Invocarea acestei funcții în „Strict Mode” va avea următorul rezultat

    UserDefinedFunction() // displays undefined
    

    Cu toate acestea, invocarea explicită a acestei funcții prin intermediul obiectului „window” va avea următorul rezultat

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

    Să ne uităm la un alt exemplu. Vă rugăm să vă uitați la următorul cod

     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
    

    În exemplul de mai sus observăm că atunci când „UserDefinedFunction” a fost invocată prin o1, „this” ia valoarea o1 și valoarea proprietăților sale „a” și „b” se afișează. Valoarea lui „c” și „d” au fost afișate ca nedefinite ca o1 nu definește aceste proprietăți

    În mod similar, atunci când „UserDefinedFunction” a fost invocată prin o2,„this” ia valoarea o2 și valoarea proprietăților sale „c” și „d” se afișează.Valoarea proprietăților „a” și „b” au fost afișate ca nedefinite ca o2 nu definește aceste proprietăți.

  3. În interiorul unui apel indirect la o „funcție nelegată”. prin functionName.call și functionName.apply:

    Atunci când o „Funcție nemijlocită” este apelată prinfunctionName.call sau functionName.apply, funcția „obiectul curent” (și, prin urmare, valoarea lui „this”) este setat la valoarea lui„this” (primul parametru) transmis către call/apply. Următorul cod demonstrează același lucru.

    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
    

    Codul de mai sus arată în mod clar că valoarea „this” pentru orice „NONBound Function” poate fi modificată prin call/apply. De asemenea, dacă valoarea„this” nu este transmis explicit către call/apply, „obiectul curent” (și, prin urmare, valoarea parametrului „this”) este setată la „window” în modul Non strict și „nedefinit” în modul strict.

  4. În interiorul apelului „Bound Function”. (adică o funcție care a fost legată prin apelarea unei funcții functionName.bind):

    O funcție legată este o funcție a cărei „this” a fost fixată. Următorul cod a demonstrat modul în care „this” funcționează în cazul unei funcții legate

    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
    

    Așa cum este prezentat în codul de mai sus, valoarea „this” pentru orice „funcție legată” NU poate fi modificată prin apelare/aplicare.. De asemenea, în cazul în care „this”nu este trecut explicit la „bind”, „obiectul curent”(și, prin urmare, valoarea parametrului „this” ) este setată la „window” în modul Nonstrict și „undefined” în modul strict. Încă un lucru: legarea unei funcții deja legate nu modifică valoarea lui „this”Aceasta rămâne la valoarea stabilită de prima funcție de legare.

  5. În timp ce crearea unui obiect prin „new”:

    În interiorul unei funcții de construcție, funcția „obiect curent” (și, prin urmare, valoarea lui „this”) face referire la obiectul care este în curs de creare prin „new” indiferent de starea de legare a funcției. Cu toate acestea, în cazul în care constructorul este o funcție legată, acesta este apelat cu un set predefinit de argumente, așa cum a fost stabilit pentru funcția legată.

  6. În interiorul gestionarului de evenimente DOM în linie:

    Vă rugăm să vă uitați la următorul fragment HTML

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

    „this” din exemplele de mai sus se referă la elementul „button” și, respectiv, la elementul „div”.

    În primul exemplu, culoarea fontului butonului va fi setată la alb atunci când se face clic pe el.

    În cel de-al doilea exemplu, atunci când elementul „div” este apăsat, se va apela la elementul OnDivClick al cărei al doilea parametru face referire la elementul div pe care s-a făcut clic. Cu toate acestea, valoarea lui „this”din OnDivClick NU TREBUIE face referire la elementul pe care s-a făcut clic divelement. Acesta trebuie să fie setat ca element „obiect fereastră” sau„nedefinit” în Non strict și Strict respectiv (dacă OnDivClick este un funcție nelegată) sau setată la o valoare predefinităBound (dacă OnDivClick este o funcție funcție legată)

În cele ce urmează se rezumă întregul articol

  1. În context global „this” se referă întotdeauna la „fereastră”

  2. Ori de câte ori este invocată o funcție, aceasta este invocată în contextul unui obiect („obiect curent”). În cazul în care obiect curent nu este furnizat în mod explicit, funcția obiect curent este „obiectul fereastră” în NON StrictMode și „nedefinit” în modul Strict, în mod implicit.

  3. Valoarea lui „this” în cadrul unei funcții Non Bound este referința la obiectul în contextul căruia este invocată funcția („current object”)

  4. Valoarea lui „this” în cadrul unei funcții non bound poate fi înlocuită de cătrecall și aplica ale funcției.

  5. Valoarea „this” este fixă pentru o funcție Bound și nu poate fi modificată de către apel și aplica metode ale funcției.

  6. Legarea unei funcții deja legate nu modifică valoarea lui „this”. Aceasta rămâne la valoarea stabilită de prima funcție de legare.

  7. Valoarea lui „this” în cadrul unui constructor este obiectul care este creat și inițializat.

  8. Valoarea lui „this” în cadrul unui gestionar de evenimente DOM în linie este referința la elementul pentru care este dat gestionarul de evenimente.

Dmitri Pavlutin

Probabil cel mai detaliat și cuprinzător articol despre this este următorul:

Explicația delicată a cuvântului cheie „this” în JavaScript

Ideea din spatele this este de a înțelege că tipurile de invocare a funcțiilor au importanța semnificativă în stabilirea this valorii.


Atunci când aveți probleme în identificarea this, nu vă întrebați:

Unde este this luat din?

ci faceți întrebați-vă:

Cum este funcția invocată?

Pentru o funcție săgeată (caz special de transparență a contextului), întrebați-vă:

Ce valoare are this în cazul în care funcția săgeată este definită?

Această mentalitate este corectă atunci când avem de-a face cu this și vă va scuti de dureri de cap.

Comentarii

  • În plus față de linkul către blogul dvs., poate ați putea aprofunda puțin mai mult modul în care adresarea acestor întrebări ajută pe cineva să înțeleagă this cuvântul cheie? –  > Por Magnus Lind Oxlund.
James Drinkard

Aceasta este cea mai bună explicație pe care am văzut-o: Înțelegeți JavaScripts acest cu claritate

The this se referă ÎNTOTDEAUNA la (și deține valoarea unui) obiect – un obiect singular – și este utilizată de obicei în interiorul unei funcții sau al unei metode, deși poate fi utilizată în afara unei funcții în domeniul global. Rețineți că, atunci când folosim modul strict, this deține valoarea de nedefinit în funcțiile globale și în funcțiile anonime care nu sunt legate de niciun obiect.

Există patru scenarii în care this poate fi derutant:

  1. Atunci când transmitem o metodă (care utilizează this) ca argument pentru a fi utilizată ca funcție de rechemare.
  2. Atunci când folosim o funcție internă (o închidere). Este important să rețineți că închiderile nu pot accesa funcția exterioară this folosind cuvântul cheie this, deoarece variabila this este accesibilă numai de către funcția în sine, nu și de către funcțiile interioare.
  3. Atunci când o metodă care se bazează pe this este atribuită unei variabile în mai multe contexte, caz în care this face referire la un alt obiect decât cel prevăzut inițial.
  4. Atunci când se utilizează this împreună cu metodele bind, apply și call.

El oferă exemple de cod, explicații și soluții, ceea ce mi s-a părut foarte util.

Nipuna

this este unul dintre conceptele neînțelese în JavaScript, deoarece se comportă puțin diferit de la un loc la altul. Pur și simplu, this se referă la „proprietarul” funcției pe care o executăm în momentul de față..

this ajută la obținerea obiectului curent (cunoscut și ca context de execuție) cu care lucrăm. Dacă înțelegeți în ce obiect se execută funcția curentă, puteți înțelege cu ușurință ce obiect curent this este

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

Mai sus am creat 3 variabile cu același nume „val”. Una în contextul global, una în interiorul obiectului și cealaltă în interiorul metodei interne a obiectului. JavaScript rezolvă identificatorii într-un anumit context prin parcurgerea lanțului de domenii de la local la global.


Câteva locuri în care this pot fi diferențiate

Apelarea unei metode a unui obiect

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

Când este executată linia1, JavaScript stabilește un context de execuție (EC) pentru apelul funcției, setând this la valoarea obiectul la care face referire ceea ce a fost înainte de ultimul „.”. deci în ultima linie se poate înțelege că a() a fost executat în contextul global, care este obiectul window.

Cu Constructorul

this poate fi folosit pentru a face referire la obiectul creat.

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

Când este nou Person() este executat, se creează un obiect complet nou. Person este apelat și se apelează this este setat pentru a face referire la acel nou obiect.

Apelarea funcției

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 

În cazul în care nu reușim new cuvântul cheie, whatIsThis se referă la cel mai global context pe care îl poate găsi(window)

Cu gestionari de evenimente

În cazul în care gestionarul de evenimente este în linie, this se referă la obiectul global

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

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

Atunci când se adaugă gestionarul de evenimente prin JavaScript, this se referă la elementul DOM care a generat evenimentul.


  • De asemenea, puteți manipula contextul utilizând .apply() .call() și .bind()
  • JQuery proxy este o altă modalitate pe care o puteți utiliza pentru a vă asigura că acest lucru într-o funcție va fi valoarea dorită. (Verificați înțelegerea utilizării $.proxy(), jQuery.proxy())
  • Ce înseamnă var that = this înseamnă în JavaScript

mrmaclean89

În termeni pseudoclasici, modul în care multe cursuri predau cuvântul cheie „this” este ca un obiect instanțiat de o clasă sau de un constructor de obiecte. De fiecare dată când un nou obiect este construit dintr-o clasă, imaginați-vă că sub capotă este creată și returnată o instanță locală a unui obiect ‘this’. Îmi amintesc că a fost predat astfel:

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;

Trombe

Valoarea lui „this” depinde de „contextul” în care este executată funcția. Contextul poate fi orice obiect sau obiectul global, adică fereastra.

Astfel, semantica lui „this” este diferită de cea a limbajelor OOP tradiționale. Și aceasta cauzează probleme:1. atunci când o funcție este transmisă unei alte variabile (cel mai probabil, un callback); și 2. atunci când o închidere este invocată dintr-o metodă membră a unei clase.

În ambele cazuri, aceasta este setată la fereastră.

Simon Groenewolt

Cine ar putea acest lucru ajutor? (Cea mai mare parte a confuziei de „this” în javascript provine din faptul că, în general, nu este legat de obiectul tău, ci de domeniul de execuție curent – s-ar putea să nu fie exact cum funcționează, dar întotdeauna mi se pare așa – vezi articolul pentru o explicație completă)

Comentarii

  • Ar fi mai bine să spunem că este legat „la contextul de execuție curent„. Cu excepția ES6 (proiect) care schimbă acest lucru cu funcțiile săgeată, unde acest lucru este rezolvat pe contextul de execuție exterior. –  > Por RobG.
unclexo

Câteva informații despre acest cuvânt cheie

Să ne înregistrăm this cuvântul cheie la consolă în domeniul global fără a mai fi nevoie de alt cod, dar

console.log(this)

În Client/Browser this cuvântul cheie este un obiect global care este window

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

și

În Server/Node/Javascript runtime this cuvântul cheie este, de asemenea, un obiect global care este module.exports

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

De reținut exports este doar o referință la module.exports

gman

Eu am o altă părere despre this față de celelalte răspunsuri, care sper să fie de ajutor.

Un mod de a privi JavaScript este de a vedea că există doar 1 singur mod de a apela o funcție1. Acesta este

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

Există întotdeauna o anumită valoare furnizată pentru objectForThis.

Orice altceva este zahăr sintactic pentru functionObject.call

Așadar, orice altceva poate fi descris prin modul în care se traduce în functionObject.call.

Dacă doar apelați o funcție, atunci this este „obiectul global”, care în browser este fereastra

Cu alte cuvinte,

foo();

a fost tradus efectiv în

foo.call(window);

Rețineți că, dacă utilizați modul strict, atunci this va fi undefined

ceea ce înseamnă

Cu alte cuvinte,

foo();

a fost tradus efectiv în

foo.call(undefined);

În JavaScript există operatori precum + și - și *. Există, de asemenea, operatorul punct, care este .

. atunci când este utilizat cu o funcție în dreapta și un obiect în stânga, înseamnă efectiv „trece obiectul ca fiind this la funcție.

Exemplu

Cu alte cuvinte bar.foo() se traduce în const temp = bar.foo; temp.call(bar);

Rețineți că nu contează cum a fost creată funcția (în mare parte…). Toate acestea vor produce aceleași rezultate

Din nou, toate acestea sunt doar zahăr sintactic pentru

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

O altă problemă este reprezentată de lanțul prototipurilor. Atunci când folosiți a.b JavaScript se uită mai întâi la obiectul la care se face referire direct prin a pentru proprietatea b. Dacă b nu este găsită pe obiect, atunci JavaScript va căuta în prototipul obiectului pentru a găsi b.

Există diverse moduri de a defini prototipul unui obiect, cel mai comun în 2019 este prototipul class cuvânt cheie. În scopuri de this totuși, nu contează. Ceea ce contează este că așa cum arată în obiect a pentru proprietatea b dacă găsește proprietatea b pe obiect sau în lanțul de prototipuri al acestuia, în cazul în care b ajunge să fie o funcție, atunci se aplică aceleași reguli ca mai sus. Funcția b vor fi apelate folosind metoda call și trecându-se metoda a ca objectForThis, așa cum se arată în partea de sus a acestui răspuns.

Acum. Să ne imaginăm că realizăm o funcție care stabilește în mod explicit this înainte de a apela o altă funcție și apoi să o apelăm cu metoda . (punct) operator

În urma traducerii pentru a utiliza call, obj.bar() devine const temp = obj.bar; temp.call(obj);. Atunci când introducem bar apelăm foo dar am trecut în mod explicit un alt obiect pentru objectForThis, astfel încât atunci când ajungem la foo this este acel obiect interior.

Aceasta este ceea ce se întâmplă în cazul în care ambele bind și => fac efectiv. Ele sunt mai mult zahăr sintactic. Ele construiesc efectiv o nouă funcție invizibilă exact ca bar de mai sus, care stabilește în mod explicit this înainte de a apela orice funcție specificată. În cazul lui bind this este setată la orice se trece la bind.

Rețineți că dacă functionObject.bind nu exista, am putea să ne facem una proprie, astfel

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

și apoi am putea să o apelăm astfel

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

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

Funcțiile de săgeată, funcția => sunt zahăr sintactic pentru bind

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

este același cu

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

La fel ca bind, se creează o nouă funcție invizibilă care apelează funcția dată cu o valoare legată pentru objectForThis dar, spre deosebire de bind obiectul care urmează să fie legat este implicit. Este orice this se întâmplă să fie atunci când => operator este utilizat.

Așadar, la fel ca în cazul regulilor de mai sus

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

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

obj.foo() se traduce în const temp = obj.foo; temp.call(obj); ceea ce înseamnă că operatorul săgeată din interiorul foo va lega obj la o nouă funcție invizibilă și va returna acea nouă funcție invizibilă care este atribuită la b. b() va funcționa așa cum a funcționat întotdeauna ca b.call(window) sau b.call(undefined) apelând noua funcție invizibilă care foo a fost creată. Această funcție invizibilă ignoră funcția this trecută în ea și trece obj ca objectForThis` la funcția săgeată.

Codul de mai sus se traduce în

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 este o altă funcție similară cu call

functionName.apply(objectForThis, arrayOfArgs);

Dar, începând cu ES6, din punct de vedere conceptual, se poate traduce chiar și în

functionName.call(objectForThis, ...arrayOfArgs);

Comentarii

  • Omule explicația ta este foarte eficientă. Mi-ați lămurit total confuzia. –  > Por John Winston.

această utilizare pentru Scope exact aș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>

valoarea lui txt1 și txt este aceeași în exemplul de mai sus $(this)=$(‘#tbleName tbody tr’) este aceeași.

Willem van der Veen

Rezumat this Javascript:

  • Valoarea lui this este determinată de modul în care este invocată funcția, nu de locul în care a fost creată!
  • De obicei, valoarea lui this este determinată de obiectul care se află în stânga punctului. (window în spațiul global)
  • În cazul ascultătorilor de evenimente, valoarea lui this se referă la elementul DOM asupra căruia a fost apelat evenimentul.
  • Atunci când funcția in este apelată cu ajutorul parametrului new valoarea lui this se referă la obiectul nou creat
  • Puteți manipula valoarea lui this cu ajutorul funcțiilor: call, apply, bind

Exemplu:

Exemplu de ascultători de evenimente:

Exemplu de constructor:

Lord

Pentru a înțelege „acest” în mod corespunzător, trebuie să înțelegem contextul, domeniul de aplicare și diferența dintre ele.

Domeniul de aplicare: În javascript, domeniul de aplicare este legat de vizibilitatea variabilelor, domeniul de aplicare se realizează prin utilizarea funcției. (Citiți mai multe despre domeniul de aplicare)

Context: Contextul este legat de obiecte. Se referă la obiectul căruia îi aparține o funcție. Atunci când utilizați cuvântul cheie JavaScript „this”, acesta se referă la obiectul căruia îi aparține funcția. De exemplu, în interiorul unei funcții, atunci când spuneți: „this.accoutNumber”, vă referiți la proprietatea „accoutNumber”, care aparține obiectului din care face parte funcția respectivă.

Dacă obiectul „myObj” are o metodă numită „getMyName”, atunci când cuvântul cheie JavaScript „this” este utilizat în cadrul „getMyName”, acesta se referă la „myObj”. În cazul în care funcția „getMyName” ar fi executată în domeniul global, atunci „this” se referă la obiectul fereastră (cu excepția modului strict).

Să vedem acum un exemplu:

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

Executarea codului abobabve în browserul de ieșire va:

Conform ieșirii, vă aflați în interiorul contextului obiectului fereastră, este de asemenea vizibil că prototipul ferestrei se referă la Obiect.

Acum să încercăm în interiorul unei funcții:

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

Output:

Ieșirea este aceeași, deoarece am înregistrat variabila „this” în domeniul global și am înregistrat-o în domeniul funcțional, nu am schimbat contextul. În ambele cazuri, contextul a fost același, legat de obiectul văduva.

Acum să creăm propriul nostru obiect. În javascript, puteți crea un obiect în mai multe moduri.

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

Ieșire:

Deci, din exemplul de mai sus, am constatat că cuvântul cheie „this” se referă la un nou context care este legat de myObj, iar myObject are, de asemenea, un lanț de prototipuri pentru Object.

Haideți să aruncăm un alt exemplu:

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

ieșire: Are sens, nu-i așa? (citiți comentariile)

Dacă aveți probleme în a înțelege exemplul de mai sus, haideți să încercăm cu propriul nostru callback;

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

ieșire:

Acum să înțelegem Scope, Self, IIFE și să vedem cum se comportă.

       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> 

Ieșirea este destul de grozavă, nu-i așa?