JavaScript:je to snadné a co o tom potřebujete vědět!

Úvod

Dovolte mi začít tento článek poděkováním čtenářům mé série JavaScript:Cracking the Nuts za to, že se jim zatím líbí a milují. Tento článek se bude zabývat dalším základním, ale stejně nepochopeným aspektem JavaScriptu, který se nazývá this klíčové slovo.

Dobře, tak začneme. Na konci článku byste měli lépe rozumět,

  • Co je toto v JavaScriptu.
  • Jak to udělat to zní méně zmateně než kdy jindy.
  • Pravidla tohoto a použití.
  • Důležité, toto je snadné!

Upozornění na dlouhé čtení ⚠️

Na rozdíl od jiných článků ze série bude tento trochu zdlouhavý. Po prostudování několika tutoriálů jsem cítil, že je třeba propojit různé aspekty, abychom pochopili koncept this studna. Například koncept call => apply => bind velmi souvisí s porozuměním this klíčové slovo. Musíme je spolu probrat.

Mohl jsem věci rozdělit do více článků, ale je lepší být spolu, protože pojmy jsou velmi propojené. Proto to dlouhé upozornění na čtení!

Vezměte si své oblíbené nápoje, odpočiňte si a začněte číst. Jsem si jistý, že si to užijete.

Co je this ?

this je klíčové slovo v JavaScriptu a jeho existence nám umožňuje vstoupit,

  • Chápat různé kontexty provádění.
  • Kontext objektu, který this souvisí s.

Pamatujte, že když je kontext spuštění vytvořen v JavaScriptu, vytvoří se speciální věc s názvem this .

  • V kontextu globálního provádění toto je rovno globálnímu window objekt.
  • V kontextu provádění funkce hodnota toto závisí na binding .

Pravidla vázání

Porozumět this funkce může být náročné klíčové slovo, protože se v JavaScriptu chová jinak než v jiných jazycích. Pokud jde o nalezení kontextu this , musíme vidět, kde je funkce vyvolána.

Použití this lze rozdělit do čtyř různých závazných aspektů.

Implicitní vazba

Implicitní vazba je nejpoužívanějším případem použití this klíčové slovo. Když vyvoláme metodu objektu, použijeme pro přístup k němu notaci tečka(.). V případě implicitní vazby kontext this je vázán na objekt, na kterém metodu vyvoláme.

Zde je příklad

Příklad:

const user = {
    name: 'GreenRoots',
    address: 'HashNode',
    greeting: function() {
        return `Hello, ${this.name} belongs to ${this.address}`
    }
};

user.greeting();

Vysvětlení: Ve výše uvedeném příkladu vyvoláme greeting() metoda na objektu uživatele pomocí notace tečka(.). Proto this je vázán na objekt uživatele. Takže this.name se chystá přihlásit GreenRoots a this.address je HashNode .

Vezměme si další příklad pro lepší vysvětlení tohoto konceptu,

Příklad:

 function greeting(obj) {
      obj.logMessage = function() {
          console.log(`${this.name} is ${this.age} years old!`);
      }
  };

  const tom = {
      name: 'Tom',
      age: 7
  };

  const jerry = {
      name: 'jerry',
      age: 3
  };

  greeting(tom);
  greeting(jerry);

  tom.logMessage ();
  jerry.logMessage ();

Vysvětlení: Ve výše uvedeném příkladu máme dva objekty, tom a jerry . Tyto objekty jsme ozdobili (vylepšili) připojením metody nazvané logMessage () .

Jen si všimněte, když voláme tom.logMessage() , metoda je vyvolána na tom objekt. Proto this vázaný na tom objekt. Totéž platí, když jerry.logMessage () je vyvoláno.

Explicitní vazba

Jsme si vědomi toho, že JavaScript vytváří prostředí pro provádění kódu, který píšeme. Toto prostředí obsahuje věci nad rámec skutečného kódu, který píšeme.

Stará se o vytvoření paměti pro proměnné, funkce, objekty atd. ve fázi vytváření. Nakonec spusťte kód ve fázi provádění. Toto speciální prostředí se nazývá JavaScript Execution Context .

Existuje mnoho takových prostředí (kontexty provádění) v aplikaci JavaScript. Každý kontext provádění je nezávislý na druhém. Ale můžeme chtít získat přístup k něčemu z jednoho kontextu provádění do druhého. Zde vstupuje do hry explicitní vazba. Pomocí toho můžeme svázat věci z jednoho kontextu do kontextu jiného prostředí .

Existují tři mimořádné metody, call() , apply() a bind() , pomůže dosáhnout explicitní vazby.

metoda call()

U metody call() bude kontext, se kterým má být funkce volána, předán jako parametr call(). Podívejme se na příklad

Příklad:

greeting: function() {
        return `Hello, ${this.name} belongs to ${this.address}`
 }

const user = {
   name: 'GreenRoots',
   address: 'HashNode'  
 };

 greeting.call(user);

Vysvětlení: Zde vidíme, že metoda call() je vyvolána ve funkci zvané greeting(). Funkce greeting() pouze zaprotokoluje zprávu pomocí this.name a this.address . Ale co je this tady? To je určeno tím, co bylo předáno metodě call().

Zde this se naváže na objekt uživatele, protože jsme předali uživatele jako parametr metodě call(). Proto this.name by měl zaznamenat hodnotu vlastnosti názvu objektu uživatele, tj. GreenRoots a podobně, this.address jako Hashnode.

Ve výše uvedeném příkladu jsme předali pouze jeden argument pro call(). V případě potřeby však můžeme volání call() předat více argumentů. Vezměme si další příklad, abychom to pochopili,

Příklad

var getName = function(hobby1, hobby2) {
     console.log(this.name + ' likes ' + hobby1 + ' , ' + hobby2);
 }
 var user = {
   name: 'Tapas',
   address: 'Bangalore'  
 };

 var hobbies = ['Swimming', 'Blogging'];
 getName.call(user, hobbies[0], hobbies[1]);

Vysvětlení: Všimněte si, že jsme zde předali další dva argumenty v metodě call(). Prvním argumentem musí být kontext objektu, se kterým má být funkce vyvolána. Ostatní parametry mohou být pouze hodnoty, které se mají použít. Zde míjím Plavání a Blogování jako dva parametry funkce getName().

Všimli jste si bodu bolesti? V případě call() je třeba argumenty předat jeden po druhém, což není tak chytrý způsob, jak věci dělat! Zde přichází na řadu naše další metoda apply().

metoda apply()

Hektický způsob předávání argumentů metodě call() lze vyřešit jinou alternativní metodou nazvanou apply(). Je to stejné jako call() ale umožňuje předávání argumentů pohodlněji. Podívejte se,

Příklad

var getName = function(hobby1, hobby2) {
     console.log(this.name + ' likes ' + hobby1 + ' , ' + hobby2);
 }
 var user = {
   name: 'Tapas',
   address: 'Bangalore'  
 };

 var hobbies = ['Swimming', 'Blogging'];
 getName.apply(user, hobbies);

Vysvětlení: Jak vidíte zde, můžeme předat pole jako argumenty, což je mnohem pohodlnější než předávání jednoho po druhém.

metodabind()

call() metoda vyvolá funkci předáním kontextu this . bind() metoda je podobná call() ale místo přímého volání funkce bind() vrací zcela novou funkci, kterou můžeme místo toho vyvolat.

Příklad:

var getName = function(hobby1, hobby2) {
     console.log(this.name + ' likes ' + hobby1 + ' , ' + hobby2);
 }
 var user = {
   name: 'Tapas',
   address: 'Bangalore'  
 };

 var hobbies = ['Swimming', 'Blogging'];
 var newFn = getName.bind(user, hobbies[0], hobbies[1]); 

 newFn();

Vysvětlení: Jak vidíme výše, getName.bind() nevyvolá funkci getName(). Vrací novou funkci newFn, kterou můžeme vyvolat jako, newFn().

nová vazba

Funkce konstruktoru je vytvořena pomocí new klíčové slovo. Zde je příklad funkce konstruktoru

var Cartoon = function(name, animal) {
     this.name = name;
     this.animal = animal;
     this.log = function() {
         console.log(this.name +  ' is a ' + this.animal);
     }
 };

Objekty můžeme vytvořit pomocí new klíčové slovo jako,

 var tom = new Cartoon('Tom', 'Cat');
 var jerry = new Cartoon('Jerry', 'Mouse');

Pojďme to rozebrat. Vezměte tento řádek,

var tom = new Cartoon('Tom', 'Cat');

Zde funkce Cartoon se vyvolá pomocí new klíčové slovo. Proto this bude vázán na zde vytvořený nový objekt, tom .

Vazba globálního objektu

Jaký bude výstup tohoto spuštění kódu? Co je this svázat sem?

var sayName = function(name) {
    // 'use strict';
    console.log(this.name);
};

window.name = 'Tapas';
sayName();

pokud this klíčové slovo není vyřešeno žádnou z výše uvedených vazeb, implicit , explicit nebo new pak this se váže k objektu window(global).

Funkce šipek, bez vazby?

ES6 zavedlo funkce šipek, které neposkytují vlastní this vazba. Jak jsme doposud viděli, v běžných funkcích this klíčové slovo představovalo objekt, který se nazývá funkce, což může být okno, dokument, uživatelsky definovaný nebo cokoli jiného.

Funkce šipek nesvazují svůj vlastní rozsah, ale zdědí jej od rodiče.

Příklad času. Uvidíme, jak to funguje.

var testHobbies = {
  hobbies: ['Cricket', 'Football', 'Blogging'],
  name: 'Alex',
  logHobbies() {
     this.hobbies.forEach((elem) => {
     console.log(`${this.name} knows ${elem}`);
  });
  }
}

Zde metoda logHobbies() iteruje koníčky a přihlásí je do konzole. Všimněte si, že v forEach používáme funkci šipky . this uvnitř funkce šipky by se vázalo na objekt testHobbies protože neexistuje this vazba pro funkce šipky a vždy se váže k nadřazené.

Vyvolání testHobbies.logHobbies() by se tedy správně zaprotokolovalo jako,

Alex knows Cricket
Alex knows Football
Alex knows Blogging

Nyní do toho vneseme zvrat. Všimněte si úpravy, kterou jsem provedl níže. Místo funkce šipky používá for-each běžnou funkci.

var testHobbies = {
  hobbies: ['Cricket', 'Football', 'Blogging'],
  name: 'Alex',
  logHobbies() {
    this.hobbies.forEach(function(elem){
    console.log(`${this.name} knows ${elem}`);
  });
  }
}

Co myslíte, this by bylo vázáno sem uvnitř forEach? Není to funkce šipky. Je to běžná funkce a má svůj vlastní kontext provádění. V tomto kontextu provádění neexistuje nic, co by se nazývalo jméno. Proto this.name není definováno.

Výstup tedy bude,

undefined knows Cricket
undefined knows Football
undefined know Blogging

Podrobněji to uvidíme v budoucích článcích na Scope a Closure .

Použít Strict a toto

Normálně v globálním rozsahu this klíčové slovo odkazuje na objekt okna,

<script>
console.log(this);  //returns window object.
</script>

V přísném režimu JavaScript také this klíčové slovo v globálním rozsahu vrátí objekt okna. V rozsahu funkcí se však chová jinak.

Viz následující příklad

<script>
        "use strict;"
        console.log(this);

        function testThis() {
            "use strict";
            console.log('testThis', this);
        }

        testThis();
    </script>

Do konzole zaprotokoluje následující výstup

Window {parent: Window, opener: null, top: Window, length: 0, frames: Window, …}
testThis undefined

Závěr

Ano, rozumím this je lehké! Ale zároveň může být náročné pochopit pravidla a použití this . Budeme rozumět this lépe, když se zaměříme na otázku, Where is the function invoked ?

Ve většině případů by použití bylo s implicitní vazbou. Bude použito s explicitní vazbou s call(), apply() a bind(). S mnoha frameworky založenými na JavaScriptu, jako je Reactjs, Angular atd., používáme funkce šipek.

Nezapomeňte, že pokud budete těmto pravidlům rozumět a budete je praktikovat, jistě budete souhlasit s tím, že this je opravdu snadné pracovat!

Kredity a zdroje

  • Krátké video YouTube od uidotdev
  • Stránky MDN o this .
  • Titulní fotka je postavena na úžasném obrázku vytvořeném brgfx na freepik.

Další užitečné zdroje na this

  • Co je to v JavaScriptu
  • Jak v Javascriptu využít váš „tento“ kontext

Doufám, že vám článek bude užitečný. Lajkujte/sdílejte, ať se to dostane i k ostatním. Pokud se vám tento článek líbil nebo vám pomohl, pojďme se připojit. Najdete mě na Twitteru (@tapasadhikary), kde sdílím myšlenky, tipy a praktiky kódování.

Chcete-li dostávat e-mailová upozornění na mé nejnovější příspěvky, přihlaste se k odběru na můj blog kliknutím na tlačítko Odebírat v horní části stránky.

Vysvětlím další základní pojmy zvané Scope a Closure v budoucích příspěvcích seriálu. Zůstaňte naladěni.