ugrás a tartalomhoz

Global scope elérése (ECMAScript feladvány)

presidento · 2010. Aug. 13. (P), 09.32
Azt mondják, a JavaScripttel az (az egyik) baj, hogy a globális változók használatát nem csak engedélyezi, hanem szinte kikényszeríti. Szerencsére nagy változást hozott ebben a tavaly decemberben elfogadott ECMAScript 5.

A kérdés: hogyan érhetjük el a kódon belül bárhonnan a globális scope-ot, avagy mit írjunk a megjegyzés helyére:
  1. var globalScope = /* ... */;  
Sajnálatos tapasztalat, hogy a legtöbb helyen (és sok keretrendszerben) szimplán window szerepel itt, ami ugye, több okból is aggályos:
  • a window elfedhető egy hasonló nevű lokális változóval
  • a window nem minden környezetben létezik (lásd: WebWorker, Server Side JS)

Figyelem: olyan kódot szeretnénk, ami tetszőleges szabványkövető ES5 környezetben a globális scope-ot adja meg (tehát strict módban is működnie kell).

Két különböző megoldás van.
 
1

Talán…

Adam · 2010. Aug. 13. (P), 10.26
Hirtelen nem jut más eszembe, csak a self vagy a content. De nem vagyok benne biztos, hogy ezek nem DOM-ban vannak csak.
2

geval

Török Gábor · 2010. Aug. 13. (P), 10.51
David Flanagan fóliái alapján ezzel versenyzem:
  1. "use strict";  
  2.   
  3. var globalScope = (function () {  
  4.     var geval = eval;  
  5.     return geval('this');  
  6. })();  
  7.   
  8. globalScope === this// true  
3

Ez az egyik

presidento · 2010. Aug. 13. (P), 12.15
Igen, ez az egyik megoldás: az indirekt eval használata.
Lehet egy sorban is:
  1. var globalScope = (0,eval)('this');  
4

(0, eval) notation

Török Gábor · 2010. Aug. 13. (P), 12.27
Ez a (0, eval) jelölés zseniális.
7

Szabad-e kérdezni?

Kevlar · 2010. Aug. 13. (P), 13.34
Gábor verzióját értem. De ez a forma nekem magas. Van ehhez vmi link, leírás, ilyesmi?
8

Ha van egy lista kifejezésed,

Török Gábor · 2010. Aug. 13. (P), 14.01
Ha van egy lista kifejezésed, akkor annak az utolsó kifejezése lesz a visszatérési érték.
  1. 0; // 0  
  2. 0, 1; // 1  
  3. 0, eval; // Function  
A 0, eval tehát az eval-lal tér vissza (indirekten hivatkozunk rá). Az így kapott függvényreferenciát hívjuk meg a 'this' argumentummal.
  1. (0, eval)('this'); // Object  
Két lépésben:
  1. var geval = (0, eval);  
  2. geval('this'); // Object  
Ez utóbbi formulánál nincs szükség a 0, eval jelölésre, elég volna a geval = eval, közvetlen hívásnál viszont máskülönben nem teljesülne az indirekt hívás. A 0 helyett gyakorlatilag bármilyen kifejezés írható, sőt, tetszőleges elem felsorolható a kifejezésbe.
10

Világos

Kevlar · 2010. Aug. 13. (P), 15.14
Köszönöm szépen!
A lista eme tulajdonságát nem ismertem.
13

Perl

Ustak · 2010. Aug. 14. (Szo), 20.32
jut az eszembe erről... Ez mindig benne volt a js-ben, és ideje lenne utánanéznem dolgoknak?
Üdv:
Gábor
14

1999

Joó Ádám · 2010. Aug. 14. (Szo), 22.11
1999-ben jelent meg az utolsó ECMAScript kiadás.
15

Zsír!

Ustak · 2010. Aug. 14. (Szo), 23.18
:-)

Azért itt más dátumot látok:
Ecma-262
Üdv:
Gábor
16

Kontextus

Joó Ádám · 2010. Aug. 15. (V), 01.30
Nyilván a kérdéses szintakszis szempontjából szóba jöhető kiadásokról beszéltem.

Egyébként semmi perles nincs benne, a C-ben is pont így működik a vessző operátor, ’72 óta. (Előzményéről nem tudok, sem BCPL-ben, sem Fortranban, sem Algolban.)
5

Szokás

Poetro · 2010. Aug. 13. (P), 13.02
Ahogy én szoktam csinálni, az a következő:
  1. (function ($, window, document) {  
  2.   // Itt lehet küzdeni, a window néve alatt elérhető a global scope,  
  3.   // akár milyen rendszer alatt, legyen az akár node.js vagy más.  
  4. })(jQuery, thisthis.document);  
6

„a kódon belül bárhonnan”

Török Gábor · 2010. Aug. 13. (P), 13.15
Ha jól értettem, akkor olyan megoldást vár Máté, ami mesterségesen beállított környezettől függetlenül képes hivatkozni a globális objektumra. Amúgy valóban ez egy pratikusan jó módszer. Kiegészítve az undefineddal, tökéletes.
12

Nekem nem tetszik

presidento · 2010. Aug. 14. (Szo), 10.50
Sajnos nem jó a megoldása: a külső függvény argumentumaiban a „this” strict módban nem a global scope-ra mutat, így a window undefined (vagy az éppen beállított this) lesz.

Praktikusan jó a megoldás, viszont hivatkozik Node.js-re, de ott nincsen sem window, sem [window.]document (de még böngészőben sem feltétlenül, lásd Web Worker). Szerintem célszerű a dolgokat a nevükön nevezni: ha a global scope kell, akkor ne window-nak hívjuk.
18

+1

inf · 2010. Aug. 15. (V), 14.08
Én is window-al szoktam elérni. Amíg ez nem változik meg a böngészőknél, addig minek használjak mást feleslegesen?
21

Web Worker

Török Gábor · 2010. Aug. 16. (H), 12.01
Pont eggyel feljebb említi Máté, hogy böngészőben sem egyértelmű a helyzet, lásd a Web Workereket, ahol nincs window. Másfelől ha a szerver oldali kód is JS, újrafelhasználható komponensek írásához nem hard-code-olhatod a window-t.
23

Hát nálam ezek speciális

inf · 2010. Aug. 16. (H), 13.10
Hát nálam ezek speciális esetnek számítanak, de igazad van. :-)
9

.call(null)

Adam · 2010. Aug. 13. (P), 14.44
Nicholas C. Zakas cikke alapján ez a másik megoldás lehet:
  1. var globalScope = (function()  
  2. {  
  3.     return this;  
  4. })();  
11

Nem jó

Török Gábor · 2010. Aug. 13. (P), 17.06
Nem, ebben az esetben ECMASCript 5 alapján undefined értéket kap a this. BESEN-nel tesztelhetők a példák.

A kódod amúgy pont annak példája, amivel megállapítható, hogy a strict mode támogatott-e.
  1. var hasstrict = (function() {  
  2.     "use strict";  
  3.     return !this;  
  4. }());  
17

Második megoldás

Török Gábor · 2010. Aug. 15. (V), 10.35
Nem írtad, hogy meddig várod a megfejtéseket. A másik megoldáshoz tudsz adni fogodzkodót?
19

jó a kérdés

presidento · 2010. Aug. 15. (V), 23.03
Szia, köszönöm a kérdést, örülök, hogy foglalkoztat.

ECMAScript 5 esetén a strict módban a this-ből nem lesz automatikusan global scope, így a kérdést úgy fogalmazhatnám meg másképpen, hogy hogyan lehet egy strict kódon belül nem strict módba jutni?

Remélem, segített.
20

Function konstruktor

Török Gábor · 2010. Aug. 16. (H), 11.55
Another important point to notice, that functions created via the Function constructor do not inherit the strictness from the surrounding context. (Forrás: ECMA-262-5 in detail. Chapter 2. Strict Mode.)
  1. "use strict";  
  2.   
  3. var globalScope = Function('return this')();  
  4. globalScope === this// true  
22

nyertél

presidento · 2010. Aug. 16. (H), 12.24
Így, ahogy írod, a másik megoldás a függvény konstruktor használata. Gratulálok! :)
24

Az miért nem jó, hogy

inf · 2010. Aug. 16. (H), 20.48
Az miért nem jó, hogy szimplán lementjük a global scope-ot valahová?

Mondjuk:
  1. "use strict";  
  2. Object.prototype.globals=this;  
25

mert nem ez volt a

Tyrael · 2010. Aug. 16. (H), 23.38
mert nem ez volt a feladat?

Tyrael
26

ok.

inf · 2010. Aug. 17. (K), 00.42
ok.