Firefox 4.0 soportará ECMAScript 5 en modo estricto (II)

4 febrero, 2011 0:16 por

Una de las funcionalidades que se resaltan en la implementación de ECMAScript 5 en modo estricto, como se mencionaba en el artículo Firefox 4 admitirá ECMAScript 5 en modo estricto es la transformación de fallos que se pasaban por alto en JavaScript por errores que lanzan excepciones.

Se mencionaba en primer lugar, que el modo estricto no permitirá la creación de variables globales de forma accidental puesto que en JavaScript normal, escribir mal una variable simplemente crea una propiedad en el objeto global. Este tipo de fallo se transformará en error y se lanzará una excepción si se esta trabajando en modo estricto:

“use strict”;

mistypedVaraible = 17; // lanza un ReferenceError

Continuando con los tipos de fallos, tenemos un segundo caso, se presenta cuando el modo estricto realiza asignaciones las cuales podrían de otra forma fallar silenciosamente lanzando una excepción. Por ejemplo, NaN no es una variables global de escritura. En el código normal una asignación a NaN no haría nada; el desarrollador no recibe notificación de fallos.  En modo estricto una asignación a NaN lanza una excepción. Alguna asignación que silenciosamente falle en código normal lanzará una excepción si se encontrara escrita en modo estricto:

“use strict”;
NaN
= 42; // lanza un TypeError
var obj = { get x() { return 17; } };
obj.
x = 5; // lanza un TypeError
var fixed = {};
Object.
preventExtensions(fixed);
fixed.
newProp = “ohai”; // lanza un TypeError

Tercero, si tratas de eliminar propiedades no eliminables, el modo estrícto lanza un error (pero antes de intentarlo podría simplemente no tener efecto):

“use strict”;
delete Object.prototype; // lanza un TypeError

Cuarto, el modo estricto requiere que todas la propiedades nombradas en un objeto literal sean únicas. En el código normal se podría duplicar los nombres de propiedades, con el último valor determinado para la propiedad. Pero desde que el último no modifique nada, la duplicación no es más que un vector de errores, si el código modifica el valor de la propiedad por otro que cambie el valor de la última instancia, duplicar nombres de propiedades es un error de sintaxis en el modo estricto:

“use strict”;
var o = { p: 1, p: 2 }; // !!! error de sintaxis

Quinto, el modo estricto requiere que los nombres de los argumentos de las funciones sean únicos.  En el código normal el último argumento duplicado esconde los últimos argumentos con el mismo nombre. Estos argumentos están disponibles por medio de arguments[i], por lo tanto no son completamente inaccesibles.  Sin embargo, esconder errores tiene poco sentido y es probablemente algo indeseable (esto podría , por ejemplo, ocultar un error), pero en el modo estricto duplicar nombres de argumentos es un error de sintaxis:

function sum(a, a, c) // !!!  error de sintaxis
{
“use strict”;
return a + b + c; // Error si este código corre
}

Sexto, el modo estricto prohíbe la sintaxis octal. La sintaxis octal no hace parte de ECMAScript, pero es soportada por todos los navegadores poniendo como prefijo un cero al número octal: 0644 === 420 and “�45″ === “%”.  Los desarrolladores novatos algunas veces creen que adicionar un cero como prefijo no tiene significado semántico, entonces lo utilizan para alinear los números en su código fuente. — Pero esto cambia el significado del número! La sintaxis octal raramente es usada y puede ser erróneamente utilizada, en este caso el modo estricto  crea un error de sintaxis en el octal:

“use strict”;
var sum = 015 + // !!!  error de sintaxis
197 +
142;

Simplificando el uso de variables

El modo estricto simplifica la forma en que las variables utilizan el mapa de definiciones de variables en el código. Muchas  optimizaciones se basan en la capacidad de saber que esta variable se encuentra en esta ubicación: esto es crítico para la completa optimización del código JavaScript. Algunas veces JavaScript  realiza el mapeo de una definición de variable  por medio de su nombre en del código fuente, lo cual  hace que sea imposible ejecutar una excepción en tiempo real.  En el modo estricto la mayoría de las veces se elimina esto en caso de que suceda, a demás el compilador puede optimizar mejor el código si esta en modo estricto.

Primero, el modo estricto prohíbe el with. El problema con el with es que cualquier nombre en el podría mapear ya sea una propiedad del objeto pasado o una variable dentro del código en tiempo de ejecución: es imposible de antemano saber a cual se refiere. El modo estricto vuelve el with un error de sintaxis, entonces no hay forma para que un nombre dentro de un with se refiera a una ubicación desconocida en tiempo de ejecución:

“use strict”;
var x = 17;
with (obj) // !!! error de sistaxis
{
// Si esto no estuviera en modo estrícto, podría ser var x o
// en su lugar podrá ser obj.x?  Es imposible en general
// decir sin ejecutar el código,  por lo cual el nombre no puede ser
// optimizado.
x
;
}

La alternativa simple de asignar el objeto a una variable, para después acceder a la correspondiente propiedad en dicha variable, continua vigente como un reemplazo para with.

Segundo: la evalución del modo estrícto no introduce nuevas variables en el código.  En un código normal eval(“var x;”) introduce una variable x en la función o en alcance global. Esto significa que, en general, en una función que contiene un llamado a eval, cada nombre no referido a un argumento o variable local, puede ser mapeado a una particular definición en tiempo real (porque ese eval podría tener introducida una nueva variable que podría esconder la variable externa). En el modo estricto, eval crea variables unicamente para el código que va a ser evaluado, entonces eval no puede afectar a un nombre que hace referencia a una variable externa o a una variable local:

var x = 17;
var evalX = eval(“‘use strict’; var x = 42; x”);
assert
(x === 17);
assert
(evalX === 42);

En relación con esto, si la función eval es invocada por una expresión de la forma eval (…) en el código en modo estricto, el código será evaluado como código en modo estricto. El código puede invocar explícitamente el modo estricto, pero no es necesario hacerlo.

function strict1(str)
{
“use strict”;
return eval(str); // str será tratado como código en modo estricto
}
function strict2(f, str)
{
“use strict”;
return f(str); // no eval(…): str es estricto sii  invoca el modo estricto
}
function nonstrict(str)
{
return eval(str); // str es estricto sii invoca el modo estricto
}
strict1
(“‘Strict mode code!’”);
strict1
(“‘use strict’; ‘Strict mode code!’”);
strict2
(eval, “‘Non-strict code.’”);
strict2
(eval, “‘use strict’; ‘Strict mode code!’”);
nonstrict
(“‘Non-strict code.’”);
nonstrict
(“‘use strict’; ‘Strict mode code!’”);

Tercero, el modo estricto prohíbe eliminar nombres sin formato.  Pero los nombres dentro del de código estricto eval se comportan de la misma forma que los nombres en modo estricto que no han sido evaluados como resultado de eval. usar delete name en modo estricto es un error de sintaxis:

“use strict”;
eval(“var x; delete x;”); // !!! error de sintaxis

Haciendo eval y arguments más simples

El modo estricto hace que eval y los argumentos sean mágicamente menos extraños. Ambos involucran  una considerable cantidad de comportamiento mágico en código normal: eval para agregar o eliminar enlaces y cambiar los valores de unión, y los arguments por sus propiedades indexadas  aliando los arguments nombrados.  El modo estricto hace grandes avances hacia el tratamiento de eval y arguments como palabras clave, aunque  una corrección completa no llegará hasta una futura edición de ECMAScript.

Primero, los nombres eval y arguments no pueden ser obligados o asignados en la sintaxis del lenguaje. Todos los intentos para hacerlo resultan en errores de sintaxis:

“use strict”;
eval = 17;
arguments
++;
++eval;
var obj = { set p(arguments) { } };
var eval;
try { } catch (arguments) { }
function x(eval) { }
function arguments() { }
var y = function eval() { };
var f = new Function(“arguments”, “‘use strict’; return 17;”);

Segundo, el código en modo estricto no crea alias a las propiedades de los arguments de los objetos creados en el. En el código normal dentro de una función cuyo primer argumento es arg, realizar una asignación a arg también sería realizar una asignación a arguments[0], y vice versa (a menos que no fueran proporcionados argumentos o arguments[0] sea eliminado). Para funciones en modo estricto, los objetos arguments almacenan los argumentos originales en el momento en que la función fué invocada. El valor de arguments[i] no realiza seguimeinto al valor del correspondiente argumento nombrado, ni un argumento nombrado puede hacer seguimiento al valor en el correspondiente arguments[i].

function f(a)
{
“use strict”;
a
= 42;
return [a, arguments[0]];
}
var pair = f(17);
assert
(pair[0] === 42);
assert
(pair[1] === 17);

Tercero, arguments.callee ya no se soporta. En código normal arguments.callee se refiere a la función adjunta. Este caso de uso es débil: simplemente el nombre de la función adjunto! Por otra parte, arguments.callee dificulta considerablemente optimizaciones como funciones inline, porque debe existir la posibilidad de proporcionar una referencia a las funciones que no son inline si se accede a arguments.callee. Para funciones en modo estricto, arguments.callee es una propiedad no eliminable, la cual lanza un error cuando se asigna o recupera:

“use strict”;
var f = function() { return arguments.callee; };
f
(); // lanza un TypeError


“Asegurar” JavaScript

El modo estricto facilita escribir JavaScrip seguro. Algunos sitios web actualmente proporcionan alternativas para que los usuarios escriban JavaScript que puede ser ejecutado por el sitio web en nombre de otros usuarios. JavaScript en los navegadores puede acceder a la información privada de los usuarios , por lo cual, JavaScript debe ser parcialmente transformado antes de ser ejecutado, para controlar el acceso a las funcionalidades no permitidas o censuradas. La flexibilidad de JavaScript  hace posible esto sin verificaciones en tiempo de ejecución. Ciertas funcionalidades del lenguaje tan dominantes que las verificaciones del rendimiento en tiempo de ejecución tienen un considerable costo en el desempeño. Unas pocas modificaciones en el modo estricto, a demás de requerirse de que el código JavaScript enviado por el usuario este en modo estricto y que sea invocado de una forma en particular, reduce substancialmente la necesidad de realizar estos chequeos en tiempo de ejecución.

Primero, el valor pasado como this a una función en modo estricto  no esta encapsulado en un objeto. Para una función normal,  el valor de this es siempre un objeto:  el objeto proporcionado sí es llamado con un valor de this; el valor encapsulado sí es llamado con un booleano, string o número de this; o el objeto global sí es llamado con un undefined o null this. (Use call, apply, o bind para especificar una particularidad de this.) El encapsulamiento automático tiene un costo de desempeño, pero exponer el objeto global en un navegador es un riesgo de seguridad, porque el objeto global proporciona acceso completo a la funcionalidad “segura” de los entornos de JavaScript que deben ser invariables. Entonces para una función en modo estricto, el this se utiliza sin cambios:

“use strict”;
function fun() { return this; }
assert
(fun() === undefined);
assert
(fun.call(2) === 2);
assert
(fun.apply(null) === null);
assert
(fun.call(undefined) === undefined);
assert
(fun.bind(true)() === true);

(Tangencialmente,  los métodos integrados tampoco estarán encapsulados si this es null o undefined. [Este cambio es independiente del modo estricto pero es motivado por la misma preocupación sobre exponer el objeto global] Históricamente, pasar null o undefined a un metodo integrado como Array.prototype.sort() podría actuar como si el objeto global hubiera sido especificado. Pero pasar uno u otro valor como this a la mayoría de los métodos integrados lanza un TypeError. Booleanos, números y strings todavía están encapsuladas por estos métodos: Esto es sólo cuando estos métodos de una u otra forma actúan sobre el objeto global que han sido cambiados.)

Segundo, en modo estricto ya nunca más será posible recorrer la pila JavaScript por medio de extensiones comúnmente implementadas para ECMAScript.  En código normal con esas extensiones, cuando una función fun está apunto de ser llamada, fun.caller es la función más reciente que ha invocado fun y fun.arguments son los argumentos para dicha invocación de fun. Ambas extensiones son problemáticas para un JavaScript “seguro”, porque permiten al código “seguro” acceder a funciones “privilegiadas” y sus (potencialmente inseguros) argumentos. Sí fun se encuentra en modo estricto, ambas fun.caller y fun.arguments son propiedades no eliminables las cuales lanzarán un error cuando se asignen o se accedan:

function restricted()
{
“use strict”;
restricted.
caller; // lanza un TypeError
restricted.
arguments; // lanza un TypeError
}
function privilegedInvoker()
{
return restricted();
}
privilegedInvoker
();

Tercero, los argumentos para el modo estricto no proporcionarán más acceso a las variables de la llamada a la función correspondiente. En algunas implementaciones antiguas de ECMAScript arguments.caller era un objeto el cual las propiedades correspondian a las variables de la función. Esto es un Problema de seguridad porque elimina la capacidad de esconder valores privilegiados de la función por medio de la abstración; Esto también se opone a la mayoría de optimizaciones. Por estas razones los navegadores recientes no las implementan. Sin embargo, debido a su funcionalidad histórica, arguments.caller en una función en modo estricto es también una propiedad no eliminable que arroja un error al asignarse o ser consultada:

“use strict”;
function fun(a, b)
{
“use strict”;
var v = 12;
return arguments.caller; // lanza un TypeError
}
fun
(1, 2); // no exponer v (or a or b)


Sentando bases para las futuras versiones de ECMAScript

Las versiones futuras de ECMAScript introducirán una nueva sintaxis, y el modo estricto en  ECMAScript 5 aplica algunas restricciones para facilitar la transición. Será más fácil que hacer algunos cambios si los fundamentos de esos cambios están prohibidos en modo estricto

Primero, en modo estricto  una lista corta de identificadores se comvierte en palabras reservadas. Esas palabras son implements, interface, let, package, private, protected, public, static, y yield. En modo estricto, por lo tanto, no es posible nombrar, usar variables, o argumentos con estos nombres. Una advertencia especifica para Mozilla: Si tu código es JavaScript 1.7 o superior (tu usas código chrome, o si has utilizado <script type=””>) y es código en modo estricto, let y yield tienen la funcionalidad que han tenido desde que esas palabras reservadas fueron introducidas. Pero en el código en modo estricto en la Web, cargado con  <script src=””> o <script>…</script>, no será posible usar let/yield como identificadores.

Segundo, el modo estricto prohíbe declaraciones de función en el nivel superior de un script o función. En código normal en los navegadores, las declaraciones de función son permitidas “en cualquier parte”. Esto no hace parte de ES5! Esta es una extensión con semántica incompatible en diferentes navegadores. Futuras ediciones de ECMAScript esperan especificar nueva semántica para evitar la declaración de funciones en la parte superior de un script o función. Prohibir tales declaraciones de función en modo estricto “aclara el panorama” para la futura especificación de las versiones de ECMAScript:

“use strict”;
if (true)
{
function f() { } // !!! error de sintaxis
f
();
}
for (var i = 0; i &lt; 5; i++)
{
function f2() { } // !!! error de sintaxis
f2
();
}
function baz() // permitido
{
function eit() { } // también permitido
}

Esta restricción no es propia del modo estricto, ya que tales declaraciones de función son extensiones. Pero es la recomendación del comité de ECMAScript, y los navegadores lo incorporarán.


Modo estricto en los Navegadores

Firefox 4 es el primer navegador que inplementa completamente el modo estrícto. El motor Nitro que se encuentra en muchos  navegadores no va más allá de un cercano soporte al modo estricto. Chrome tiene también started para implementar el modo estricto. Internet Explorer y Opera no han iniciado la implementación del modo estricto; puede tomarse la libertad de enviar preguntas a los fabricantes de esos navegadores sugiriendo soporte para modo estricto.

Los navegadores  seguramente no implementarán el modo estrícto, porque no dependen ciegamente de el. El modo estricto cambia la semántica.  Basándose en esos cambios se causarán fallas y errores en los navegadores que no implementan el modo estricto. Tenga cuidado en el uso del modo estricto, y haga copias de seguridad de las dependencias en modo estricto con las funcionalidades de prueba para comprobar que las características pertinentes de modo estricto están implementadas.

Para probar el modo estricto, descargue Firefox nightly e inicia tus pruebas. También considera estas restricciones cuando escribas nuevo código y cuando actualices código existente. (para estar absolutamente seguro, sin embargo es probablemente mejor esperar a usarlo en producción, hasta que este soportado en los navegadores)

Fuente: Mozilla Hacks.

Conviertiendo fallas en errores

El modo estrícto cambia fallas pasadas por alto a errores. JavaScript fué diseñado para ser fácil para los desarolladores notavos, y algunas veces ofrece operaciones que pueden cambiar algunas fallas en errores. Algunas veces esto soluciona el problema inmediatos, pero también podría crear problemas peores en el futuro. El modo estricto trata estos fallos como errores para que sean ubicados y corregidos rápidamente.

En primer lugar, el modo estricto no permite crear accidentalmente variables globales. En JavaScript normal, escribir mal una variable simplemente crea una propiedad en el objeto global y se continúa con el “trabajo” (aunque el fracaso futuro es posible: es probable, en el actual JavaScript). Las asignaciones que accidentalmente crea variables globales podrían lanzar una excepción si se esta trabajando en modo estricto:

“use strict”;

mistypedVaraible = 17; // lanza un ReferenceError

Segundo, el modo estrícto realiza asignaciones las cuales podrían de otra forma fallar sileciosamente lanzando una excepción. Por ejemplo, NaN no es una variables global de escritura. En el código normal una asignación a NaN no haría nada; el desarrollador no recibe notificación de fallos.  En modo estrćto una asignación a NaN lanza una excepción. Alguna asignación que silenciosamente falle en códogo normal lanzará una excepción si se encontrata escrita en modo estricto:

“use strict”;
NaN
= 42; // lanza un TypeError
var obj = { get x() { return 17; } };
obj.
x = 5; // lanza un TypeError
var fixed = {};
Object.
preventExtensions(fixed);
fixed.
newProp = “ohai”; // lanza un TypeError

Tercero, Si tratas de eliminar propiedades no eliminables, el modo estrícto lanza un error (pero antes de intentarlo podría simplemente no tener efecto):

“use strict”;
delete Object.prototype; // lanza un TypeError

Cuarto, el modo estricto requiere que todas la propiedades nombradas en un objeto literal sean únicas. En el código normal se podría duplicar los nombres de propiedades, con el último valor determinado para la propiedad. Pero desde que el último no modifique nada, la duplicación no es más que un vector de errores, si el código modifica el valor de la propiedad por otro que cambie el valor de la última instancia, duplicar nombres de propiedades es un error de sintaxis en el modo estrícto:

“use strict”;
var o = { p: 1, p: 2 }; // !!! error de sintaxis

Quinto, el modo estrícto requiere que los nombres de los argumentos de las funciones sean únicos.  En el código normal el último argumento duplicado esconde los últimos argumentos con el mismo nombre. Estos argumentos están disponibles por medio de arguments[i], por lo tanto no son completamente inaccesibles.  Sin embargo, esconder errores tiene poco sentido y es probablemente algo indeseable (esto podría , por ejemplo, ocultar un error), pero en el modo estricto duplicar nombres de argumentos es un error de sintaxis:

function sum(a, a, c) // !!!  error de sintaxis
{
“use strict”;
return a + b + c; // Error si este código corre
}

Sexto, el modo estricto prohíbe la sintáxis octal. La sintáxis octal no hace parte de ECMAScript, pero es soportada por todos los navegadores poniendo como prefijo un cero al número octal: 0644 === 420 and “�45″ === “%”.  Los desarrolladores novatos algunas veces creen que adicionar un cero como prefijo no tiene significado semántico, entonces lo utilizan para alinear los números en su código fuente. — Pero esto cambia el significado del número! La sintaxis octal raramente es usada y puede ser erroneamente utilizada, en este caso el modo estricto  crea un error de sintaxis en el octal:

“use strict”;
var sum = 015 + // !!!  error de sintaxis
197 +
142;

Simplificando el uso de variables

El modo estícto simplifica la forma en que las variables utilizan el mapa de definiciones de variables en el código. Muchas  optimizaciones se basan en la capacidad de saber que esta variable se encuentra en esta ubicación: esto es crítico para la completa optimización del código JavaScript. Algunas veces JavaScript  realiza el mapeo de una deficinión de variable  por medio de su nombre en del código fuente, lo cual  hace que sea imposible ejecutar una excepción en tiempo real.  En el modo estrícto la mayoría de las veces se elimina esto en caso de que suceda, a demás el compilador puede optimizar mejor el código si esta en modo estŕcto.

Primero, el modo estrícto prohibe el with. El priblema con el with es que cualquier nombre en el podría mapear ya sea una propiedad del objeto pasado o una variable dentro del código en tiempo de ejecución: es imposible de antemano saber a cual se refiere. El modo estrícto vuelve el with un error de sintaxis, entonces no hay forma para que un nombre dentro de un with se refiera a una ubicación desconocida en tiempo de ejecución:

“use strict”;
var x = 17;
with (obj) // !!! error de sistaxis
{
// Si esto no estuviera en modo estrícto, podría ser var x o
// en su lugar podrá ser obj.x?  Es imposible en general
// decir sin ejecutar el código,  por lo cual el nombre no puede ser
// optimizado.
x
;
}

La alternativa simple de asignar el objeto a una variable, para después acceder a la correspondiente propiedad en dicha variable, continua vigente como un reemplazo para with.

Segundo, la evalución del modo estrícto no introduce nuevas variables en el código.  En un código normal eval(“var x;”) introduce una variable x en la función o en alcance global. Esto significa que, en general, en una función que contiene un llamado a eval, cada nombre no referido a un argumento o variable local, puede ser mapeado a una particular definicion en tiempo real (porque ese eval podría tener introducida una nueva variable que podria esconder la variable externa). En el modo estrícto, eval crea variables unicamente para el código que va a ser evaluado, entonces eval no puede afectar a un nombre que hace referencia a una variable externa o a una variable local:

var x = 17;
var evalX = eval(“‘use strict’; var x = 42; x”);
assert
(x === 17);
assert
(evalX === 42);

En relación con esto, si la función eval es invocada por una expresión de la forma eval (…) en el código en modo estricto, el código será evaluado como código en modo estricto. El código puede invocar explícitamente el modo estricto, pero no es necesario hacerlo.

function strict1(str)
{
“use strict”;
return eval(str); // str será tratado como código en modo estricto
}
function strict2(f, str)
{
“use strict”;
return f(str); // no eval(…): str es estricto sii  invoca el modo estricto
}
function nonstrict(str)
{
return eval(str); // str es estricto sii invoca el modo estricto
}
strict1
(“‘Strict mode code!’”);
strict1
(“‘use strict’; ‘Strict mode code!’”);
strict2
(eval, “‘Non-strict code.’”);
strict2
(eval, “‘use strict’; ‘Strict mode code!’”);
nonstrict
(“‘Non-strict code.’”);
nonstrict
(“‘use strict’; ‘Strict mode code!’”);

Tercero, El modo estricto prohíbe eliminar nombres sin formato.  Pero los nombres dentro del de código estricto eval se comportan de la misma forma que los nombres en modo estricto que no han sido evaluados como resultado de eval. usar delete name en modo estricto es un error de sintaxis:

“use strict”;
eval(“var x; delete x;”); // !!! error de sintaxis

Haciendo eval y arguments más simples

El modo estricto hace que eval y los argumentos sean mágicamente menos extraños. Ambos involucran  una considerable cantidad de comportamiento mágico en código normal: eval para agregar o eliminar enlaces y cambiar los valores de unión, y los arguments por sus propiedades indexadas  aliando los arguments nombrados.  El modo estricto hace grandes avances hacia el tratamiento de eval y arguments como palabras clave, aunque  una corrección completa no llegará hasta una futura edición de ECMAScript.

Primero, los nombres eval y arguments no pueden ser obligados o asignados en la sintaxis del lenguaje. Todos los intentos para hacerlo resultan en errores de sintaxis:

“use strict”;
eval = 17;
arguments
++;
++eval;
var obj = { set p(arguments) { } };
var eval;
try { } catch (arguments) { }
function x(eval) { }
function arguments() { }
var y = function eval() { };
var f = new Function(“arguments”, “‘use strict’; return 17;”);

Segundo, el código en modo estricto no crea alias a las propiedades de los arguments de los objetos creados en el. En el código normal dentro de una función cuyo primer argumento es arg, realizar una asignación a arg también sería realizar una asignación a arguments[0], y vice versa (a menos que no fueran proporcionados argumentos o arguments[0] sea eliminado). Para funciones en modo estricto, los objetos arguments almacenan los argumentos originales en el momento en que la función fué invocada. El valor de arguments[i] no realiza seguimeinto al valor del correspondiente argumento nombrado, ni un argumento nombrado puede hacer seguimiento al valor en el correspondiente arguments[i].

function f(a)
{
“use strict”;
a
= 42;
return [a, arguments[0]];
}
var pair = f(17);
assert
(pair[0] === 42);
assert
(pair[1] === 17);

Tercero, arguments.callee ya no se soporta. En código normal arguments.callee se refiere a la función adjunta. Este caso de uso es débil: simplemente el nombre de la función adjunto! Por otra parte, arguments.callee dificulta considerablemente optimizaciones como funciones inline, porque debe existir la posibilidad de proporcionar una referencia a las funciones que no son inline si se accede a arguments.callee. Para funciones en modo estricto, arguments.callee es una propiedad no eliminable, la cual lanza un error cuando se asigna o recupera:

“use strict”;
var f = function() { return arguments.callee; };
f
(); // lanza un TypeError

“Asegurar” JavaScript

El modo estricto facilita escribir JavaScrip seguro. Algunos sitios web actualmente proporcionan alternativas para que los usuarios escriban JavaScript que puede ser ejecutado por el sitio web en nombre de otros usuarios. JavaScript en los navegadores puede acceder a la información privada de los usuarios , por lo cual, JavaScript debe ser parcialmente transformado antes de ser ejecutado, para controlar el aceso a las funcionalidades no permitidas o censuradas. La flexibilidad de JavaScript  hace posible esto sin verificaciones en tiempo de ejecución. Ciertas funcionalidades del lenguaje tan dominantes que las verificaciones del rendimiento en tiempo de ejecución tienen un considerable costo en el desempeño. Unas pocas modificaciones en el modo estricto, a demás de requerirse de que el código JavaScript enviado por el usuario este en modo estricto y que sea invocado de una forma en particular, reduce substancialmente la necesidad de realizar estos chequeos en tiempo de ejecución.

Primero, el valor pasado como this a una función en modo estricto  no esta encapsulado en un objeto. Para una función normal,  el valor de this es siempre un objeto:  el objeto proporcionado sí es llamado con un valor de this; el valor encapsulado sí es llamado con un booleano, string o número de this; o el objeto global sí es llamado con un undefined o null this. (Use call, apply, o bind para especificar una particularidad de this.) El encapsulamiento automático tiene un costo de desempeño, pero exponer el objeto global en un navegador es un riesgo de seguridad, porque el objeto global proporciona acceso completo a la funcionalidad “segura” de los entornos de JavaScript que deben ser invariables. Entonces para una función en modo estricto, el this se utiliza sin cambios:

“use strict”;
function fun() { return this; }
assert
(fun() === undefined);
assert
(fun.call(2) === 2);
assert
(fun.apply(null) === null);
assert
(fun.call(undefined) === undefined);
assert
(fun.bind(true)() === true);

(Tangencialmente,  los metodos integrados tampoco estarán encapsulados si this es null o undefined. [Este cambio es independiente del modo estricto pero es motivado por la misma preocupación sobre exponer el objeto global] Historicamente, pasar null o undefined a un metodo integrado como Array.prototype.sort() podría actuar como si el objeto global hubiera sido especificado. Pero pasar uno u otro valor como this a la mayoría de los métodos integrados lanza un TypeError. Booleanos, números y strings todavía estan encapsuladas por estos métodos: Esto es sólo cuando estos métodos de una u otra forma actúan sobre el objeto global que han sido cambiados.)

Segundo, en modo estricto ya nunca más será posible recorrer la pila JavaScript por medio de extensiones comunmente implementadas para ECMAScript.  En código normal con esas extensiones, cuando una función fun está apunto de ser llamada, fun.caller es la función más reciente que ha invocado fun y fun.arguments son los argumentos para dicha invocacion de fun. Ambas extensiones son problematicas para un JavaScript “seguro”, porque permiten al código “seguro” acceder a funciones “privilegiadas” y sus (potencialmente insuguros) argumentos. Sí fun se encuentra en modo estrícto, ambas fun.caller y fun.arguments son propiedades no eliminables las cuales lanzarán un error cuando se asignen o se accedan:

function restricted()
{
“use strict”;
restricted.
caller; // lanza un TypeError
restricted.
arguments; // lanza un TypeError
}
function privilegedInvoker()
{
return restricted();
}
privilegedInvoker
();

Tercero, los argumentos para el modo estricto no proporcionarán más acceso a las variables de la llamada a la función correspondiente. En algunas implementaciones antiguas de ECMAScript arguments.caller era un objeto el cual las propiedades correspondian a las variables de la función. Esto es un Problema de seguridad porque elimina la capacidad de esconder valores privilegiados de la función por medio de la abstración; Esto también se opone a la mayoría de optimizaciones. Por estas razones los navegadores recientes no las implementan. Sin embargo, debido a su funcionalidad histórica, arguments.caller en una función en modo estricto es también una propiedad no eliminable que arroja un error al asignarse o ser consultada:

“use strict”;
function fun(a, b)
{
“use strict”;
var v = 12;
return arguments.caller; // lanza un TypeError
}
fun
(1, 2); // no exponer v (or a or b)

Sentando bases para las futuras versiones de ECMAScript

Las versiones futuras de ECMAScript introducirán una nueva sintaxis, y el modo estricto en  ECMAScript 5 aplica algunas restricciones para facilitar la transición. Será más fácil que hacer algunos cambios si los fundamentos de esos cambios están prohibidos en modo estricto

Primero, en modo estricto  una lista corta de identificadores se comvierte en palabras reservadas. Esas palabras son implements, interface, let, package, private, protected, public, static, y yield. En modo estricto, por lo tanto, no es posible nombrar, usar variables, o argumentos con estos nombres. Una advertencia especifica para Mozilla: Si tu código es JavaScript 1.7 o superior (tu usas código chrome, o si has utilizado <script type=””>) y es código en modo estricto, let y yield tienen la funcionalidad que han tenido desde que esas palabras reservadas fueron introducidas. Pero en el código en modo estricto en la Web, cargado con  <script src=””> o <script>…</script>, no será posible usar let/yield como identificadores.

Segundo,el modo estricto prohíbe declaraciones de función en el nivel superior de un script o función. En código normal en los navegadores, las declaraciones de función son permitidas “en cualquier parte”. Esto no hace parte de ES5! Esta es una extensión con semántica incompatible en diferentes navegadores. Futuras ediciones de ECMAScript esperan especificar nueva semántica para evitar la declaración de funciones en la parte superior de un script o función. Prohibir tales declaraciones de función en modo estricto “aclara el panorama” para la futura especificación de las versiones de ECMAScript:

“use strict”;
if (true)
{
function f() { } // !!! error de sintaxis
f
();
}
for (var i = 0; i &lt; 5; i++)
{
function f2() { } // !!! error de sintaxis
f2
();
}
function baz() // permitido
{
function eit() { } // también permitido
}

Esta restricción no es propia del modo estricto, ya que tales declaraciones de función son extensiones. Pero es la recomendación del comité de ECMAScript, y los navegadores lo incorporarán.

Modo estricto en los Navegadores

Firefox 4 es el primer navegador que inplementa completamente el modo estrícto. El motor Nitro que se encuentra en muchos  navegadores no va más allá de un cercano soporte al modo estricto. Chrome tiene también started para implementar el modo estricto. Internet Explorer y Opera no han iniciado la implementación del modo estricto; Puede tomarse la libertad de enviar preguntas a los fabricantes de esos navegadores  sugiriendo soporte para modo estricto.

Los navegadores  seguramente no implementarán el modo estrícto, porque no dependen ciegamente de el. El modo estricto cambia la semántica.  Basándose en esos cambios se causarán fallas y errores en los navegadores que no implementan el modo estricto. Tenga cuidado en el uso del modo estricto, y haga copias de seguridad de las dependencias en modo estricto con las funcionalidades de prueba para comprobar que las características pertinentes de modo estricto están implementadas.

Para probar el modo esricto, descarga Firefox nightly e inicia tus pruebas. También considera estas restricciones cuando escribas nuevo código y cuando actualices código existente. (para estar absolutamente seguro, sin embargo es probablemente mejor esperar a usarlo en producción, hasta que este soportado en los navegadores)

Fuente: Mozilla Hacks.

The following two tabs change content below.

Compartir artículo:

  • ¡Participa!

    Firefox Flicks »
    Crear un vídeo sobre Firefox ahora tiene premio.
    Firefox Affiliates »
    Agrega botones de Firefox en tu sitio web y comparte tu amor por Mozilla Firefox.
    Armada alucinante »
    Ayuda a otros usuarios en Twitter.
    Desafío para desarrolladores »
    Envía tu demo y gana muchos premios.
    Colabora con la comunidad »
    En Mozilla lo importante son las personas. Descubre cómo puedes colaborar.

    Boletín Firefox

    Suscríbete al boletín de novedades de Firefox.

  • Descargas

    Descarga los programas de Mozilla.

    Lo más visto

    cc-by-sa