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

"use strict";

var globalScope = (function () {
    var geval = eval;
    return geval('this');
})();

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

0; // 0
0, 1; // 1
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.

(0, eval)('this'); // Object
Két lépésben:

var geval = (0, eval);
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ő:
(function ($, window, document) {
  // Itt lehet küzdeni, a window néve alatt elérhető a global scope,
  // akár milyen rendszer alatt, legyen az akár node.js vagy más.
})(jQuery, this, this.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:

var globalScope = (function()
{
    return this;
})();
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.

var hasstrict = (function() {
    "use strict";
    return !this;
}());
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.)

"use strict";

var globalScope = Function('return this')();
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:

"use strict";
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.