JavaScript 101-#22 – Rozsah, kontext a toto

Proměnné jsou základem JavaScriptu a každého dalšího programovacího jazyka. Bez patřičných znalostí o nich se daleko nedostanete. Proměnným jsme se však již věnovali v jednom z předchozích příspěvků. Dnes se zaměříme na další téma úzce související s proměnnými a také důležité. Toto téma je rozsah. V tomto příspěvku si procvičíme práci s proměnnými, funkcemi a dalšími v různém rozsahu. Bez dalších řečí začněme!

Poznámka

Abyste si mohli procvičit kód, který dnes použijeme, nepotřebujete na svém počítači nainstalované žádné IDE (pokud žádné nemáte). Můžete také použít některé online možnosti, jako je Codepen.io, JSBin, JSFiddle, nebo si ve svém prohlížeči vybrat konzolu pro vývojáře. Nebojte se také souborů HTML nebo CSS, budeme pracovat pouze s JavaScriptem.

Rozsah

Pokud jde o rozsah, máme dvě možnosti. Můžeme pracovat buď s globální působností, nebo lokální. A je to. Toto jsou jediné dostupné typy. Jaký je v tom rozdíl? Cokoli (proměnná, funkce, objekt) definované v globálním rozsahu je a bude přístupné z jakékoli části programu (souboru skriptu). Na druhou stranu ke kódu definovanému v místním rozsahu (uvnitř objektu, funkce nebo uzávěru) lze přistupovat pouze v tomto konkrétním rozsahu. Žádný kód zvenčí s ním nemůže pracovat.

Abychom si to lépe představili, ukažme si to na několika příkladech. Nejprve vytvoříme několik proměnných, funkcí a objektů v globálním rozsahu.

JavaScript:

// global scope
var scope = “global”;
var float = 3.14;
var boolean = false;
function say () { … };
var spencer = new Object();

Všechny proměnné, funkce řekni a objekt spencer jsou definovány v globálním rozsahu, takže s nimi můžete pracovat, manipulovat s nimi a také je libovolně měnit v jakékoli části skriptu.

JavaScript:

// global scope
var scope = “global”;
var float = 3.14;
var boolean = false;
function say () {
 return scope;
};
var spencer = new Object();
spencer.favNumber = float;

console.log(say()); // “global”
console.log(spencer.favNumber); // 3.14
scope = “Still global?”; // value of the scope variable is now “Still global?”
console.log(jump()); // “Still global?”
boolean = true; // value of the boolean variable is now “true”

Nyní to trochu změníme a přejdeme k místnímu rozsahu. Vezmeme proměnné definované v příkladu výše a zabalíme je do nového objektu. Od této chvíle tedy budou tyto proměnné definovány v lokálním rozsahu – rozsahu objektu – a budou přístupné pouze uvnitř objektu nebo jeho prostřednictvím pomocí tečkové notace.

JavaScript:

var variables = {
 scope: “local”,
 float: 3.14,
 boolean: false,
 say: function() {
 return this.scope;
 },
 spencer: new Object()
}

spencer.favNumber = float; // error – spencer is not defined
console.log(spencer.favNumber); // error – spencer is not defined
console.log(say()); // - error – say is not defined

Jak vidíte, kdykoli se pokusíte získat přístup k nějakému kódu vytvořenému uvnitř proměnné objektu, dostanete chybu. Mimo tento objekt žádná z proměnných, funkce nebo objektu (spencer) neexistuje. Když se tedy pokusíme změnit hodnotu oboru mimo objekt, kde je definována, vytvoří se nová proměnná s názvem scope v globálním rozsahu při zachování původní nedotčené.

JavaScript:

var variables = {
 scope: “local”,
 float: 3.14,
 boolean: false,
 say: function() {
 return this.scope;
 },
 spencer: new Object()
}

scope = "Still local?"; // creates new variable
console.log(scope); // "Still local?" (new variable)
console.log(variables.scope); // “local” (variable created in “variables” object)

Je to skvělý způsob, jak chránit kód před přepsáním. Další výhodou použití místního rozsahu je výkon. Protože jsme všechny proměnné vytvořili do objektu, neexistují a nemají tedy žádný vliv na mezipaměť prohlížeče. Prohlížeč je vytvoří, pouze pokud přistoupíme k objektu proměnná nebo nějakou proměnnou uvnitř pomocí tečkové notace.

JavaScript:

var variables = {
 scope: “local”,
 float: 3.14,
 boolean: false,
 say: function() {
 return this.scope;
 },
 spencer: new Object()
}

console.log(variables.scope); // “local”
console.log(variables.float); // 3.14
console.log(variables.boolean); // false
console.log(variables.say()); // “local”
console.log(variables.spencer); // [object Object] { … }

Kontext a toto

Možná si všimnete tohoto klíčové slovo uvnitř say funkce. Pomocí tohoto pracujeme v kontextu proměnných objekt, a proto odkazujeme na rozsah proměnná uvnitř tohoto objektu. Co když přidáme novou globální proměnnou scope a vytvořte novou funkci odkazující na rozsah bez tohoto klíčové slovo?

JavaScript:

var variables = {
 scope: “local”,
 float: 3.14,
 boolean: false,
 say: function() {
 return this.scope;
 },
 // new function without “this” keyword
 check: function() {
 return scope;
 },
 spencer: new Object()
}

// new scope
var scope = “I'm global!”;
console.log(variables.say()); // “local”
console.log(variables.check()); // “I'm global!”

Vidět? Když jsme vynechali toto klíčové slovo v kontrole funkce se změnil i kontext. Rozsah proměnná nyní odkazuje na rozsah proměnná vytvořená v globálním rozsahu. Pokud odstraníme rozsah proměnná v globálním rozsahu, kontrola funkce vrátí chybu – rozsah není definován.

Když mluvíme o tomto a kontextu, pojďme se podrobně podívat na to, jak fungují. Abychom to úplně pochopili, vytvoříme další objekt joshua . Oba, spencer a joshua , bude mít křestní jméno , příjmení a věk proměnná, ale spencer bude také pozdravit funkce se zprávou, která bude používat toto uvést v něm své jméno a věk. Později vytvoříme novou funkci greetStolen pro joshuu a odkazujte na pozdrav uvnitř spencer objekt.

JavaScript:

// object spencer
var spencer = {
 firstName: “Spencer”,
 lastName: “Crowly”,
 age: 25,
 greeting: function() {
 console.log(“Hi, my name is “ + this.firstName + “ “ + this.lastName + “ and I am “ + this.age + “ years old.”);
 }
};

spencer.greeting(); // “Hi, my name is Spencer Crowly and I am 25 years old.”

// new object joshua
var joshua = {
 firstName: “Joshua”,
 lastName: “Sick”,
 age: 19
};

// attaching greeting function to joshua
joshua.greetStolen = spencer.greeting;

// calling the greetStolen function
joshua.greetStolen(); // “Hi, my name is Joshua Sick and I am 19 years old.”

Čekal jsi tohle? Pokud ne, věřte mi, neexistuje žádná magie ani temné tajemství. Jak bylo řečeno výše, toto vždy odkaz na místní kontext – kontext objektu, ve kterém je použit. Takže, i když ukradneme pozdrav funkce pro spencer a připojte jej k joshuovi , toto obsažené uvnitř funkce udělá to, co má – odkaz na místní kontext -> joshua objekt. Pamatujte si pokaždé, když toto použijete uvnitř nějakého objektu bude vždy odkazovat na data uvnitř tohoto objektu.

Shrnutí

No, to je vše. Doufám, že vám tento příspěvek pomůže pochopit rozdíl mezi místním a globálním rozsahem a jak kontext a toto práce s klíčovými slovy. Pokud máte nějaké dotazy k tomuto nebo jinému tématu, zanechte komentář nebo mi napište zprávu. Jsem tu, abych vám pomohl. Děkujeme za váš čas.