Metody objektů, toto

Objekty jsou obvykle vytvářeny tak, aby reprezentovaly entity skutečného světa, jako jsou uživatelé, objednávky a tak dále:

let user = {
 name: "John",
 age: 30
};

A v reálném světě může uživatel jednat :vybrat něco z nákupního košíku, přihlášení, odhlášení atd.

Akce jsou v JavaScriptu reprezentovány funkcemi ve vlastnostech.

Příklady metod

Pro začátek se naučíme user pozdravit:

let user = {
 name: "John",
 age: 30
};

user.sayHi = function() {
 alert("Hello!");
};

user.sayHi(); // Hello!

Zde jsme právě použili funkční výraz k vytvoření funkce a přiřazení k vlastnosti user.sayHi objektu.

Pak to můžeme nazvat jako user.sayHi() . Uživatel nyní může mluvit!

Funkce, která je vlastností objektu, se nazývá jeho metoda .

Takže tady máme metodu sayHi objektu user .

Samozřejmě bychom mohli jako metodu použít předem deklarovanou funkci, jako je tato:

let user = {
 // ...
};

// first, declare
function sayHi() {
 alert("Hello!");
}

// then add as a method
user.sayHi = sayHi;

user.sayHi(); // Hello!
Objektově orientované programování

Když píšeme náš kód pomocí objektů k reprezentaci entit, nazývá se to objektově orientované programování, stručně:„OOP“.

OOP je velká věc, zajímavá vlastní věda. Jak vybrat ty správné subjekty? Jak zorganizovat interakci mezi nimi? To je architektura a na toto téma existují skvělé knihy, jako například „Design Patterns:Elements of Reusable Object-Oriented Software“ od E. Gamma, R. Helma, R. Johnsona, J. Vissidese nebo „Object-Oriented Analysis and Design with Applications“ od G. Boocha a další.

Zkratka metody

V objektovém literálu existuje kratší syntaxe pro metody:

// these objects do the same

user = {
 sayHi: function() {
 alert("Hello");
 }
};

// method shorthand looks better, right?
user = {
 sayHi() { // same as "sayHi: function(){...}"
 alert("Hello");
 }
};

Jak bylo ukázáno, můžeme vynechat "function" a stačí napsat sayHi() .

Abych řekl pravdu, zápisy nejsou zcela totožné. Existují jemné rozdíly související s dědičností objektů (budou pokryty později), ale zatím na nich nezáleží. Téměř ve všech případech je preferována kratší syntaxe.

„toto“ v metodách

Je běžné, že objektová metoda potřebuje ke své práci přistupovat k informacím uloženým v objektu.

Například kód v user.sayHi() může vyžadovat název user .

Pro přístup k objektu může metoda použít this klíčové slovo.

Hodnota this je objekt „před tečkou“, ten, který se používá k volání metody.

Například:

let user = {
 name: "John",
 age: 30,

 sayHi() {
 // "this" is the "current object"
 alert(this.name);
 }

};

user.sayHi(); // John

Zde během provádění user.sayHi() , hodnota this bude user .

Technicky je také možné přistupovat k objektu bez this , odkazem na něj prostřednictvím vnější proměnné:

let user = {
 name: "John",
 age: 30,

 sayHi() {
 alert(user.name); // "user" instead of "this"
 }

};

…Ale takový kód je nespolehlivý. Pokud se rozhodneme zkopírovat user do jiné proměnné, např. admin = user a přepište user s něčím jiným, pak přistoupí k nesprávnému objektu.

To je ukázáno níže:

let user = {
 name: "John",
 age: 30,

 sayHi() {
 alert( user.name ); // leads to an error
 }

};


let admin = user;
user = null; // overwrite to make things obvious

admin.sayHi(); // TypeError: Cannot read property 'name' of null

Pokud bychom použili this.name místo user.name uvnitř alert , pak by kód fungoval.

„toto“ není vázáno

V JavaScriptu klíčové slovo this se chová na rozdíl od většiny ostatních programovacích jazyků. Může být použit v jakékoli funkci, i když to není metoda objektu.

V následujícím příkladu není žádná syntaktická chyba:

function sayHi() {
 alert( this.name );
}

Hodnota this se vyhodnocuje během běhu v závislosti na kontextu.

Například zde je stejná funkce přiřazena dvěma různým objektům a má odlišné „toto“ ve volání:

let user = { name: "John" };
let admin = { name: "Admin" };

function sayHi() {
 alert( this.name );
}

// use the same function in two objects
user.f = sayHi;
admin.f = sayHi;

// these calls have different this
// "this" inside the function is the object "before the dot"
user.f(); // John (this == user)
admin.f(); // Admin (this == admin)

admin['f'](); // Admin (dot or square brackets access the method – doesn't matter)

Pravidlo je jednoduché:if obj.f() je voláno a poté this je obj během volání f . Takže je to buď user nebo admin ve výše uvedeném příkladu.

Volání bez objektu:this == undefined

Funkci můžeme dokonce volat zcela bez objektu:

function sayHi() {
 alert(this);
}

sayHi(); // undefined

V tomto případě this je undefined v přísném režimu. Pokud se pokusíme získat přístup k this.name , dojde k chybě.

V nepřísném režimu hodnota this v takovém případě to bude globální objekt (window v prohlížeči, k němu se dostaneme později v kapitole Globální objekt). Toto je historické chování, které "use strict" opravy.

Obvykle je takové volání chybou programování. Pokud je zde this uvnitř funkce očekává, že bude volána v kontextu objektu.

Důsledky nevázání this

Pokud pocházíte z jiného programovacího jazyka, pak jste pravděpodobně zvyklí na myšlenku "svázaného this ", kde metody definované v objektu mají vždy this odkazující na tento objekt.

V JavaScriptu this je „free“, jeho hodnota se vyhodnocuje při volání a nezávisí na tom, kde byla metoda deklarována, ale spíše na tom, jaký objekt je „před tečkou“.

Koncept run-time vyhodnocen this má plusy i mínusy. Na jedné straně lze funkci znovu použít pro různé objekty. Na druhou stranu větší flexibilita vytváří více možností pro chyby.

Zde není naším postojem posuzovat, zda je toto rozhodnutí o návrhu jazyka dobré nebo špatné. Pochopíme, jak s tím pracovat, jak získat výhody a vyhnout se problémům.

Funkce šipek nemají žádné „toto“

Funkce šipek jsou speciální:nemají „vlastní“ this . Pokud odkazujeme na this z takové funkce je převzata z vnější „normální“ funkce.

Například zde arrow() používá this z vnějšího user.sayHi() metoda:

let user = {
 firstName: "Ilya",
 sayHi() {
 let arrow = () => alert(this.firstName);
 arrow();
 }
};

user.sayHi(); // Ilya

To je speciální funkce funkcí šipek, je to užitečné, když ve skutečnosti nechceme mít samostatný this , ale spíše to brát z vnějšího kontextu. Později v kapitole Revidované funkce šipek půjdeme hlouběji do funkcí šipek.

Shrnutí

  • Funkce, které jsou uloženy ve vlastnostech objektu, se nazývají „metody“.
  • Metody umožňují objektům „chovat se“ jako object.doSomething() .
  • Metody mohou odkazovat na objekt jako this .

Hodnota this je definován za běhu.

  • Když je funkce deklarována, může používat this , ale to this nemá žádnou hodnotu, dokud není funkce volána.
  • Funkci lze kopírovat mezi objekty.
  • Pokud je funkce volána v syntaxi „metody“:object.method() , hodnota this během hovoru je object .

Upozorňujeme, že funkce šipek jsou speciální:nemají this . Když this je přístupná uvnitř funkce šipky, je převzata zvenčí.