2012-03-09 12 views
20

¿Cuál es la forma recomendada de obtener un identificador para el global object en el modo estricto ES5 en un entorno de host desconocido?Obtener una referencia al objeto global en un entorno desconocido en el modo estricto

ECMAScript no proporciona una forma incorporada para hacer referencia al objeto global del que soy consciente. Si lo hace, esta es la respuesta que estoy buscando.

En un entorno conocido, el objeto global suele tener una propiedad autorreferencial. Puesto que el objeto global es el VO para el ámbito mundial, las propiedades del objeto global son variables globales, por lo que puede utilizarlos obtener un identificador para el objeto global desde cualquier lugar:

  • En un navegador web, podemos use window o self.

  • En node.js, podemos usar global.

Sin embargo, este no es necesariamente el caso en todos los entornos de host. Por lo que sé, Windows Script Host no proporciona ninguna forma de acceder al objeto global. La forma recomendada de obtener el objeto global en WSH parece ser utilizar la palabra clave this en un contexto donde no se resuelve en un objeto. Por ejemplo:

var GLOBAL = (function(){return this}()); 

Esta técnica funcionará para cualquier entorno de acogida, pero no en el modo estricto, ya que un indefinido this no hacer referencia al objeto global en strict mode:

Si esto se evalúa dentro de un estricto modo de código, entonces este valor no se coacciona a un objeto. A este valor de nulo o indefinido no se convierte en el objeto global y los valores primitivos no se convierten en objetos contenedoras. Este valor pasado a través de una llamada a función (incluidas las llamadas realizadas con Function.prototype.apply y Function.prototype.call) no obliga a pasar este valor a un objeto (10.4.3, 11.1.1, 15.3.4.3, 15.3. 4.4).

Como se esperaba, el código siguiente produce en undefined:

(function(){ 
    "use strict"; 
    var GLOBAL = (function(){return this}()); 
    console.log(GLOBAL); 
}()); 

Así que, ¿cuál es la forma correcta de obtener un identificador para el objeto global en cualquier ambiente, sin importar el modo estricto?

Por cierto, mi enfoque actual es para olfatear para las variables globales que hacen referencia al objeto global como esto:

var self, window, global = global || window || self; 

... y luego sólo tiene que utilizar global. Creo que esta es una mala solución por varias razones, la mayoría de las cuales son bastante obvias y no abordan el problema de WSH.

+1

no pudo hacer ''use strict'; (función (global) {}) (esto) '? (No probé esto en absoluto). – Marshall

+0

Eso funciona en Node.js, al menos, @Marshall –

+0

@DavidEllis Woops, esa es mi plataforma de elección O_o Creo que debería consultarlo en otros antes de decir algo;) – Marshall

Respuesta

29

En ES5, se puede obtener una referencia al objeto global desde el interior de modo estricto a través de llamada eval indirecta:

"use strict"; 
var global = (1,eval)('this'); 

Tome un vistazo a my article; particularmente en este section on strict mode.

+0

gracias por la respuesta, he leído muchos de sus artículos (que son excelentes por cierto) pero me he perdido esta. Pensé en usar 'eval', pero no sabía acerca de este truco de indirección (simplemente usar' eval' sin indirecciones en el alcance de la función, obviamente). –

+0

Gracias por las amables palabras :) Hablando de truco de eval, he escuchado algo acerca de que Node.js no sigue el comportamiento de ES5 en ese sentido y de que hay otra magia ocurriendo detrás de las escenas. Nunca tuve la oportunidad de probarlo, por lo que es posible que desee verificarlo nuevamente. Sin embargo, funciona en todos los navegadores que he probado, y debería funcionar en teoría, ya que así está especificado en ES5. – kangax

+0

Lo probaré en un nodo ... si está roto en un nodo, puedo hacer que compruebe si existe un 'global' ya existente para solucionarlo (y cambiarle el nombre a 'global' en el ejemplo por otra cosa) no sombreará el 'global' existente si se llama desde el alcance de la función). Esto es exactamente lo que estaba buscando, gracias. –

1

En modo estricto, la manera de obtener una referencia al objeto global es asignar una variable en el objeto global que hace referencia a sí mismo.

Eso es this means the global object when in the global context, por lo que la solución es simple:

"use strict"; 
var global = global || this; 
(function() { global.hello = "world"; })(); 
console.log(hello); // Outputs 'world' as expected 

Este ¿significa que usted tiene que contaminar el espacio de nombres global con una referencia a sí mismo, pero como usted dice, que ya debería haber sido ahí.

+0

Espera, ¿no fallará la referencia a 'global' a menos que use un cheque' typeof'? –

+2

@wilmoore: No, porque la instrucción 'var' se iza. 'var global = global || this; 'se procesa efectivamente como' var global; global = global || esto; '.Si 'global' ya existe,' var global' es un no-op, de lo contrario se crea con un valor inicial de 'undefined', que luego se sobrescribe en la siguiente instrucción. –

+0

Sí, cuando originalmente publiqué, sabía sobre 'var' izar, pero para ser sincero, no lo armé en este contexto particular. Gracias por el aviso :) –

7

En global code, el thisBinding se establece en el objeto global independientemente del modo estricto. Eso significa que puede pasarlo desde allí a su módulo IEFE:

// "use strict"; or not 
(function(global) { 
    "use strict"; 
    … 
    console.log(global); 
    … 
}(this)); 
+0

En realidad es similar a la respuesta de @DavidEllis, pero sin contaminar el alcance global :-) – Bergi

Cuestiones relacionadas