En los últimos tiempos se ha satanizado la orden
with
, por parte de personas de renombre como el mismo Douglas Crockford. En su artículo
With
statement considered harmful explica que, a pesar de ser similar a otros lenguajes, la falta en JavaScript de que un bloque tenga un ámbito propio puede fomentar errores difíciles de detectar. Si dentro del bloque del
with
se asigna un valor a una variable, no hay forma de saber si se está haciendo sobre un miembro del objeto pasado con el
with
o si se está modificando una variable global:
var bing=1;
with(ooo.eee.ooo.eee.ooo) {
bing=2;
}
// en este punto, que toma el valor 2?
// bing==2 o ooo.eee.ooo.eee.ooo.bing==2
De hecho
propone en sus recomendaciones para la próxima versión de ECMAScript que está orden sea declarada obsoleta.
Sin embargo las cosas no son tan sencillas como parecen. De nuevo, Andrea Giammarchi
le saca punta al asunto como
ya hizo con la polémica del
desconocido segundo parámetro de
eval
, acusando a los que lo quitaban del lenguaje de perder una oportunidad perfecta de generar un entorno controlado para ejecutar secuencias en las que no se confía. Y también pasó con la propuesta de eliminar
callee
ante la que Andrea
defendió que no se hiciese.
Con esta sencilla estructura se consigue mucha más potencia que con el uso tradicional pasando al
with
una variable con un objeto:
with({o:myreference}){
o.doStuff();
o.var1 = "loquesea";
// etc etc ...
};
También se facilita construcciones commo la siguiente que resulta extremadamente compacta y, por tanto, poco susceptible de ganar espacio con una compresión de código tradicional:
with(document)
with(documentElement)
insertBefore(
createElement("script"),
firstChild
)
.text = "alert(1)"
;
Sólo que además permite aprovechar esa definición
en línea del parámetro-objeto para realizar llamadas a funciones, usar el operador terciario ( condicion ? cierto : falso ), o especificar parámetros por defecto:
// ejemplo de argumentos con nombre y sin usar closures
with({
obj:myObject,
// valores por defecto en línea por si acaso
collection:collection || [],
callback:myCaseAnalyzer,
// variables locales
i:0,
length:collection ? collection.length : 0,
// variable local no inicializada
tmp:null
}){
for(;i < length; ++i){
tmp = callback.call(obj, collection[i]);
if(tmp){
tmp.doStuff();
collection[i] = tmp;
};
};
};
Que resulta ser equivalente a los típicos
closures tan utilizados. Otro uso interesante sería la tradicional llamada Ajax:
with(this.XMLHttpRequest ?
new XMLHttpRequest :
new ActiveXObject("Microsoft.MSXML")
){
open("get", "?ajax=true", true);
onreadystatechange = function(){
if(readyState === 4)
// realiza acciones con responseText/XML
alert(responseText)
;
};
send(null);
}
¿Quién es Douglas Crockford?
ResponderEliminarhttp://en.wikipedia.org/wiki/Douglas_Crockford
ResponderEliminarDouglas Crockford es un programador estadounidense y emprendedor, conocido principalmente por su implicación en el desarrollo del lenguaje JavaScript, y por haber popularizado el formato de datos JSON (JavaScript Object Notation).