2009-12-18 9 views
31

Duplicar posibles:
Are there legitimate uses for JavaScript’s “with” statement?"con la" palabra clave en javascript

Recientemente he descubierto que en javascript, uno puede hacer algo como lo siguiente:

with document{ 
    write('foo'); 
    body.scrollTop = x; 
} 

El lado negativo de esto es que cada variable debe verificarse para ver si pertenece al objeto del documento, creando una sobrecarga significativa.

Alternativamente, se podría hacer algo como esto:

var d = document; 
d.write('foo'); 
d.body.scrollTop = x; 

¿Hay situaciones en las que se justifica el uso de palabras clave de la 'con'?

Respuesta

12

Estas son algunas entradas del blog en apoyo de la con la palabra clave. ¡Pero por favor lea la entrada del blog de YUI que azazul también publicó!

http://webreflection.blogspot.com/2009/12/with-worlds-most-misunderstood.html http://webreflection.blogspot.com/2009/12/with-some-good-example.html

+0

@Abel, tienes razón, esto responde muy bien a mi pregunta y también incluye una advertencia importante allí. –

+3

@Annie: Creo que debería pegar algunas citas aquí en lugar de simplemente vincular dos artículos relacionados. ¿Qué sucede si conducen a un código HTTP 404 (o similar) más tarde (por ejemplo, porque estos artículos fueron movidos/eliminados)? – Sk8erPeter

+1

** No se recomienda el uso de 'with', y está prohibido en el modo estricto ECMAScript 5. La alternativa recomendada es asignar el objeto cuyas propiedades desea acceder a una variable temporal. ** Fuente: [Mozilla Developer Network] (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference)/Estados de cuenta/con) – Pankaj

50

Simplemente no lo use: with comunicado http://yuiblog.com/blog/2006/04/11/with-statement-considered-harmful/

de JavaScript tenía por objeto proporcionar una forma abreviada de escribir recurrentes accesos a los objetos. Así que en lugar de escribir

ooo.eee.oo.ah_ah.ting.tang.walla.walla.bing = true; 
ooo.eee.oo.ah_ah.ting.tang.walla.walla.bang = true; 

Puede escribir

with (ooo.eee.oo.ah_ah.ting.tang.walla.walla) { 
    bing = true; 
    bang = true; 
} 

que se parece mucho más agradable. Excepto por una cosa. No hay forma de que pueda verlo mirando el código que bing y bang serán modificados. ¿Se modificará ooo.eee.oo.ah_ah.ting.tang.walla.walla? ¿O las variables globales bing y bang quedarán destrozadas? Es imposible saber con certeza ...

Si no puede leer un programa y está seguro de que sabe lo que va a hacer, no puede confiar en que va a funcionar correctamente. Por esta razón, la declaración with debe evitarse ...

+2

No puedo expresar esto lo suficiente: cualquier sintaxis similar a "con", como la de JavaScript y Delphi, donde no se especifica explícitamente qué identificadores pertenecen al objeto "con ámbito" y cuál no , son ** evil **, no use esa sintaxis en esos idiomas. En particular, los cambios futuros podrían modificar el comportamiento de ese código sin previo aviso. Si eso no es un error que está esperando que ocurra, entonces no sé qué es. –

+1

Por ejemplo, Visual Basic.NET lo hizo bien, http://msdn.microsoft.com/en-us/library/wc500chb(VS.80).aspx, donde lo obligan a prefijar todos los identificadores que pertenecen al objeto del ámbito con un punto –

+0

Sí, VB (.NET y versiones anteriores) lo hicieron bien, pero también lo entendieron mal: si usas el enlace de último momento, sigues teniendo el mismo problema. Y el rendimiento con 'with' es más lento que sin (por alguna razón extraña). – Abel

5

Me gustaría evitar su uso en el código de producción porque es ambigua, pero no es una solución alternativa a la solución de bucle cerrado utilizando with para imitar la let unión, aquí está una copia de mi respuesta anterior:

una alternativa a la solución de cierre estándar utilizando funciones dentro de un bucle for:

<a href="#">blah</a><br> 
<a href="#">blah</a><br> 
<a href="#">foo</a><br> 
<script> 
    (function() { 
    var anchors = document.getElementsByTagName('a'); 
     for (var i = anchors.length; i--;) { 
      var link = anchors[i]; 
      with ({ number: i }) { 
       link.onclick = function() { 
        alert(number); 
       }; 
      } 
     } 
    })(); 
</script> 

crédito a nlogax para proporcionar una solución que yo más o menos un timo: Javascript infamous Loop issue?

Aquí está la solución patrón:

<script> 
    (function() { 
    var anchors = document.getElementsByTagName('a'); 
    for (var i = anchors.length; i--;) { 
     var link = anchors[i]; 
     (function(i) { 
      link.onclick = function() { 
       alert(i) 
      } 
     })(i); 
    } 
    })(); 
</script> 
+2

Asegúrese de indicar qué parte es "ambigua", ya que el intérprete y/o compilador JavaScript nunca se confunde sobre qué usar para el identificador. Son los cambios futuros y/o lo que un programador podría interpretar un identificador ya que ese es el problema. –

12

A pesar del consejo en sentido contrario en casi todas partes, creo que hay usos para "con". Por ejemplo, estoy trabajando en un marco de modelo de dominio para Javascript, que usa el carácter de subrayado de la misma manera que jQuery usa "$". Esto significa que sin "con", tengo muchos guiones bajos diseminados a través de mi código de maneras que lo hacen menos legible. Aquí hay una línea al azar desde una aplicación utilizando el marco:

_.People().sort(_.score(_.isa(_.Parent)),'Surname','Forename'); 

mientras que con "con" que se vería así

with (_) { 
    ... 

    People().sort(score(isa(Parent)),'Surname','Forename'); 

    ... 
} 

Lo que sería realmente útil es una versión de sólo lectura de "con".

+0

No siempre el tiempo de ejecución más lento le da efectos secundarios. Es insignificante si no lo ejecutas mil veces. – kroe

+2

En estos días, con la desestructuración de objetos ES6, podría hacer 'const {People, score, isa, Parent} = _;', y no provocar todos los riesgos desagradables de 'with (_)'. –

Cuestiones relacionadas