Los comentarios de Alan Storm en respuesta a mi respuesta con respecto a la with
declaración me hicieron pensar. Raramente he encontrado una razón para usar esta característica del lenguaje en particular, y nunca he pensado mucho en cómo podría causar problemas. Ahora, tengo curiosidad acerca de cómo podría hacer un uso efectivo with
, evitando sus dificultades.
¿Dónde has encontrado with
útil la declaración?
with
por lo que ya no existe tal cosa.Respuestas:
Se me ocurrió otro uso hoy, así que busqué en la web con entusiasmo y encontré una mención existente: Definición de variables dentro de Block Scope .
Antecedentes
JavaScript, a pesar de su parecido superficial con C y C ++, no abarca las variables del bloque en el que se definen:
Declarar un cierre en un ciclo es una tarea común en la que esto puede conducir a errores:
Debido a que el bucle for no introduce un nuevo alcance, las tres funciones compartirán el mismo
num
, con un valor de2
.Un nuevo alcance:
let
ywith
Con la introducción de la
let
declaración en ES6 , resulta fácil introducir un nuevo alcance cuando sea necesario para evitar estos problemas:O incluso:
Hasta que ES6 esté universalmente disponible, este uso permanece limitado a los navegadores y desarrolladores más nuevos dispuestos a usar transpiladores. Sin embargo, podemos simular fácilmente este comportamiento usando
with
:El ciclo ahora funciona según lo previsto, creando tres variables separadas con valores de 0 a 2. Tenga en cuenta que las variables declaradas dentro del bloque no tienen alcance, a diferencia del comportamiento de los bloques en C ++ (en C, las variables deben declararse al comienzo de un bloque, por lo que en cierto modo es similar). Este comportamiento es en realidad bastante similar a una
let
sintaxis de bloque introducida en versiones anteriores de los navegadores Mozilla, pero no ampliamente adoptada en otros lugares.fuente
for (var i = 0; i < 3; ++i) { setTimeout ((function () { var num = i; return function () { alert (num); }; }) (), 10);}
var toString = function () { return "Hello"; }; with ({"test":1}) { console.log(toString()); };
. En el ámbito de la instrucción with , toString () es una propiedad heredada de Object , por lo que no se llama a la función definida explícitamente. Sin embargo, sigue siendo una gran respuesta :-)He estado usando la declaración with como una forma simple de importación con ámbito. Digamos que tiene un generador de marcado de algún tipo. En lugar de escribir:
En su lugar, podría escribir:
Para este caso de uso, no estoy haciendo ninguna tarea, por lo que no tengo el problema de ambigüedad asociado con eso.
fuente
context.bezierCurveTo
cien veces seguidas, puede decirvar bc2 = context.bezierCurveTo;
y luego irbc2(x,x,etc);
cada vez que quiera llamarlo. Eso es bastante rápido e incluso menos detallado, mientras quewith
es súper lento.Como lo indicaron mis comentarios anteriores, no creo que pueda usarlo de
with
manera segura, sin importar lo tentador que pueda ser en cualquier situación. Como el problema no está cubierto directamente aquí, lo repetiré. Considere el siguiente códigoSin investigar cuidadosamente esas llamadas de función, no hay forma de saber cuál será el estado de su programa después de que se ejecute este código. Si
user.name
ya estaba configurado, ahora lo estaráBob
. Si no se estableció, el globalname
se inicializará o cambiará aBob
y eluser
objeto permanecerá sin unaname
propiedad.Los errores suceden. Si se utiliza con el que finalmente va a hacer esto y aumentar las posibilidades de su programa fallará. Peor aún, puede encontrar un código de trabajo que establece un global con el bloque with, ya sea deliberadamente o a través del autor, sin saber acerca de esta peculiaridad de la construcción. Es muy parecido a encontrarse con un interruptor, no tiene idea de si el autor lo intentó y no hay forma de saber si "arreglar" el código introducirá una regresión.
Los lenguajes de programación modernos están repletos de funciones. Se descubre que algunas características, después de años de uso, son malas y deben evitarse. Javascript
with
es uno de ellos.fuente
De hecho, la
with
declaración me pareció increíblemente útil recientemente. Esta técnica nunca se me ocurrió hasta que comencé mi proyecto actual: una consola de línea de comandos escrita en JavaScript. Estaba tratando de emular las API de la consola Firebug / WebKit donde se pueden ingresar comandos especiales en la consola pero no anulan ninguna variable en el ámbito global. Pensé en esto al tratar de superar un problema que mencioné en los comentarios a la excelente respuesta de Shog9 .Para lograr este efecto, utilicé dos con declaraciones para "superponer" un alcance detrás del alcance global:
Lo mejor de esta técnica es que, aparte de las desventajas de rendimiento, no sufre los temores habituales de la
with
declaración, porque de todos modos estamos evaluando en el ámbito global: no hay peligro de que las variables fuera de nuestro pseudo-alcance sean modificado.Me inspiró publicar esta respuesta cuando, para mi sorpresa, logré encontrar la misma técnica utilizada en otros lugares: ¡el código fuente de Chromium !
EDITAR: Acabo de verificar la fuente de Firebug, encadenan 4 con declaraciones juntas para incluso más capas. ¡Loco!
fuente
Si, si y si. Hay un uso muy legítimo. Reloj:
Básicamente, cualquier otro gancho DOM o CSS son usos fantásticos de with. No es que "CloneNode" esté indefinido y vuelva al ámbito global a menos que se salga de su camino y decida hacerlo posible.
La queja de velocidad de Crockford es que se crea un nuevo contexto con. Los contextos son generalmente caros. Estoy de acuerdo. Pero si acaba de crear un div y no tiene un marco disponible para configurar su CSS y necesita configurar 15 o más propiedades CSS a mano, entonces crear un contexto probablemente será más barato que la creación de variables y 15 desreferencias:
etc ...
fuente
with
. Sin embargo, en este caso particular, podría hacer:element.style.cssText="background: black ; color: blue ; border: 1px solid green"
extend
método de cualquiera de jQuery o Underscore.js:$.extend(element.style, {fontWeight: 'bold', fontSize: '1.5em', color: '#55d', marginLeft: '2px'})
..css()
método ...Puede definir una pequeña función auxiliar para proporcionar los beneficios
with
sin la ambigüedad:fuente
with_
ser una versión duplicada fangosa(function(_){ _.a="foo"; })(object_here);
(la forma estándar de simular bloques de estilo c / java). Use eso en su lugar.Apenas parece que valga la pena, ya que puede hacer lo siguiente:
fuente
with
.Nunca uso, no veo una razón para hacerlo, y no lo recomiendo.
El problema
with
es que evita numerosas optimizaciones léxicas que puede realizar una implementación de ECMAScript. Dado el aumento de los motores rápidos basados en JIT, este problema probablemente será aún más importante en el futuro cercano.Puede parecer que
with
permite construcciones más limpias (cuando, por ejemplo, introduce un nuevo alcance en lugar de una función anónima común o reemplaza el alias detallado), pero realmente no vale la pena . Además de una disminución del rendimiento, siempre existe el peligro de asignar a una propiedad de un objeto incorrecto (cuando no se encuentra la propiedad en un objeto en el alcance inyectado) y tal vez introducir erróneamente variables globales. IIRC, este último tema es el que motivó a Crockford a recomendar evitarwith
.fuente
with(){}
construcciones como las que se dan en otras respuestas aquí, en los navegadores modernos, me encantaría ver ¡ellos!with(){}
: configurar un nuevo alcancewith
es enormemente costoso en cada navegador que probé. Desea evitar esto en cualquier código llamado con mucha frecuencia. Además, Chrome exhibió un éxito dramático para cualquier código que se ejecute dentro de unwith()
alcance. Curiosamente, IE tenía las mejores características de rendimiento para el código dentro de loswith()
bloques: factorizar el costo de configuración,with()
proporciona el medio más rápido de acceso de miembros en las máquinas virtuales IE6 e IE8 (aunque estas máquinas virtuales son las más lentas en general). Buenas cosas, gracias ...with()
es casi un orden de magnitud más lento en Chrome, y más del doble de rápido en IE ...!Visual Basic.NET tiene una
With
declaración similar . Una de las formas más comunes en que lo uso es establecer rápidamente una serie de propiedades. En vez de:, Puedo escribir:
Esto no es solo una cuestión de pereza. También hace que el código sea mucho más legible. Y a diferencia de JavaScript, no sufre de ambigüedad, ya que debe prefijar todo lo afectado por la declaración con un
.
(punto). Entonces, los dos siguientes son claramente distintos:vs.
El primero es
someObject.Foo
; este último estáFoo
en el alcance exteriorsomeObject
.Creo que la falta de distinción de JavaScript lo hace mucho menos útil que la variante de Visual Basic, ya que el riesgo de ambigüedad es demasiado alto. Aparte de eso,
with
sigue siendo una idea poderosa que puede mejorar la legibilidad.fuente
Puede usar
with
para introducir el contenido de un objeto como variables locales en un bloque, como se está haciendo con este pequeño motor de plantillas .fuente
Usar "con" puede hacer que su código sea más seco.
Considere el siguiente código:
Puedes secarlo de la siguiente manera:
Supongo que depende de si tienes preferencia por la legibilidad o la expresividad.
El primer ejemplo es más legible y probablemente se recomienda para la mayoría de los códigos. Pero la mayoría del código es bastante manso de todos modos. El segundo es un poco más oscuro, pero usa la naturaleza expresiva del lenguaje para reducir el tamaño del código y las variables superfluas.
Me imagino que las personas a las que les gusta Java o C # elegirían la primera forma (object.member) y las que prefieren Ruby o Python elegirían la última.
fuente
Creo que el uso obvio es como un atajo. Si, por ejemplo, está inicializando un objeto, simplemente guarde escribiendo mucho "ObjectName". Algo así como "con-slots" de lisp que te permite escribir
que es lo mismo que escribir
Es más obvio por qué este es un acceso directo que cuando su idioma permite "Objectname.foo" pero aún así.
fuente
with-slots
requiere que especifique qué ranuras está usando, mientraswith
que usará cualquier ranura que esté vinculada en tiempo de ejecución.Al tener experiencia con Delphi, diría que usar con debería ser una optimización de tamaño de último recurso, posiblemente realizada por algún tipo de algoritmo de minimización de JavaScript con acceso al análisis de código estático para verificar su seguridad.
Los problemas de alcance que puede tener con el uso liberal de la declaración with pueden ser un verdadero problema en el a ** y no quisiera que nadie experimente una sesión de depuración para descubrir qué está pasando en su código. , solo para descubrir que capturó un miembro de objeto o la variable local incorrecta, en lugar de la variable de alcance global o externo que pretendía.
El VB con declaración es mejor, ya que necesita los puntos para desambiguar el alcance, pero el Delphi con declaración es un arma cargada con un disparador de hairt, y me parece que el javascript es lo suficientemente similar como para garantizar la misma advertencia.
fuente
No se recomienda usar con, 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.org
fuente
La instrucción with puede usarse para disminuir el tamaño del código o para miembros de clases privadas, por ejemplo:
La instrucción with es muy útil si desea modificar el alcance, lo que es necesario para tener su propio alcance global que pueda manipular en tiempo de ejecución. Puede ponerle constantes o ciertas funciones auxiliares que se usan a menudo como, por ejemplo, "toUpper", "toLower" o "isNumber", "clipNumber", etc.
Sobre el mal rendimiento que leo a menudo: el alcance de una función no tendrá ningún impacto en el rendimiento, de hecho, en mi FF, una función de alcance se ejecuta más rápido que un sin alcance:
Entonces, de la manera mencionada anteriormente, la declaración with no tiene un efecto negativo en el rendimiento, pero es bueno, ya que disminuye el tamaño del código, lo que afecta el uso de la memoria en los dispositivos móviles.
fuente
Usar con también hace que su código sea más lento en muchas implementaciones, ya que ahora todo queda envuelto en un alcance adicional para la búsqueda. No hay una razón legítima para usar con JavaScript.
fuente
var obj={a:0,b:0,c:0};var d=+new Date;with(obj){for(var i=0;i<1000000;++i){a+=1;b+=1;c+=1}}+new Date-d;
da un promedio de 2500, mientras quevar obj={a:0,b:0,c:0};var d=+new Date;for(var i=0;i<1000000;++i){obj.a+=1;obj.b+=1;obj.c+=1}+new Date-d;
da un promedio de 750, haciendo que el que usa sea más de 3 veces más lento.with
código y 903 sin él. Con esta pequeña diferencia, incluso en un ciclo cerrado, haría una selección basada en la simplicidad de codificación y la facilidad de refactorización caso por caso antes de preocuparme por el rendimiento.Creo que la declaración with puede ser útil al convertir un lenguaje de plantilla en JavaScript. Por ejemplo, JST en base2 , pero lo he visto con más frecuencia.
Estoy de acuerdo en que uno puede programar esto sin la declaración with. Pero debido a que no da ningún problema, es un uso legítimo.
fuente
Es bueno para poner código que se ejecuta en un entorno relativamente complicado en un contenedor: lo uso para hacer un enlace local para "ventana" y para ejecutar código destinado a un navegador web.
fuente
Creo que el uso literal del objeto es interesante, como un reemplazo directo para usar un cierre
o con la declaración equivalente de un cierre
Creo que el riesgo real es accidentalmente minipular variables que no son parte de la declaración with, por lo que me gusta el objeto literal con el que se pasa, puede ver exactamente lo que será en el contexto agregado en el código.
fuente
Creé una función de "fusión" que elimina parte de esta ambigüedad con la
with
declaración:Puedo usarlo de manera similar
with
, pero sé que no afectará ningún alcance que no pretendo que afecte.Uso:
fuente
Para algunas piezas de código cortas, me gustaría usar las funciones trigonométricas como
sin
,cos
etc. en modo grado en lugar de en modo radiante. Para este propósito, uso unAngularDegree
objeto:Entonces puedo usar las funciones trigonométricas en modo de grado sin más ruido de lenguaje en un
with
bloque:Esto significa: uso un objeto como una colección de funciones, que habilito en una región de código limitado para acceso directo. Esto me parece útil.
fuente
with
declaración de esta manera, solo hace que el código sea difícil de leer porque no sabe qué función es global y qué función se llama en el ámbito de con objeto, por lo que si alguna función no está definida en el alcance del objeto, entonces intentará acceder a él en el espacio de nombres globalz = Math.atan2( Math.sin(d * Math.PI / 180), Math.cos( pol.lat * Math.PI / 180) * Math.tan( pos.lat * Math.PI / 180 ) - Math.sin( pol.lat * Math.PI / 180 ) * Math.cos( d * Math.PI / 180) ) * 180 / Math.PI;
daría el mismo resultado, pero es el horror.with
que te dejarían perplejo.Creo que la utilidad de
with
puede depender de qué tan bien esté escrito su código. Por ejemplo, si está escribiendo un código que aparece así:entonces podría argumentar que
with
mejorará la legibilidad del código al hacer esto:Por el contrario, se podría argumentar que está violando la Ley de Deméter , pero, de nuevo, tal vez no. Me estoy desviando =).
Por encima de todo, sepa que Douglas Crockford recomienda no usar
with
. Le insto a que consulte su publicación de blog sobrewith
y sus alternativas aquí .fuente
Simplemente no veo cómo usar el with es más legible que simplemente escribir object.member. No creo que sea menos legible, pero tampoco creo que sea más legible.
Como dijo lassevk, definitivamente puedo ver cómo usar con sería más propenso a errores que simplemente usar la sintaxis muy explícita "object.member".
fuente
Debe ver la validación de un formulario en javascript en W3schools http://www.w3schools.com/js/js_form_validation.asp donde el formulario del objeto se "escanea" para encontrar una entrada con el nombre 'correo electrónico'
Pero lo modifiqué para obtener de CUALQUIER formulario todos los campos se validan como no vacíos, independientemente del nombre o la cantidad de campo en un formulario. Bueno, he probado solo campos de texto.
Pero con () hizo las cosas más simples. Aquí está el código:
fuente
La bifurcación Coco de CoffeeScript tiene una
with
palabra clave, pero simplemente se establecethis
(también se puede escribir como@
en CoffeeScript / Coco) al objeto de destino dentro del bloque. Esto elimina la ambigüedad y logra el cumplimiento del modo estricto ES5:fuente
Aquí hay un buen uso para
with
: agregar nuevos elementos a un objeto literal, en función de los valores almacenados en ese objeto. Aquí hay un ejemplo que acabo de usar hoy:Tenía un conjunto de fichas posibles (con aberturas hacia arriba, abajo, izquierda o derecha) que se podían usar, y quería una forma rápida de agregar una lista de fichas que siempre se colocarían y bloquearían al comienzo del juego. . No quería seguir escribiendo
types.tbr
para cada tipo en la lista, así que simplemente lo uséwith
.fuente
Puede usar with para evitar tener que administrar explícitamente arity cuando use require.js:
Implementación de requirejs.declare:
fuente
Como Andy E señaló en los comentarios de la respuesta de Shog9, este comportamiento potencialmente inesperado ocurre cuando se usa
with
con un objeto literal:No es que el comportamiento inesperado ya no fuera un sello distintivo
with
.Si realmente desea utilizar esta técnica, al menos use un objeto con un prototipo nulo.
Pero esto solo funcionará en ES5 +. Tampoco lo uses
with
.fuente
Estoy trabajando en un proyecto que permitirá a los usuarios cargar código para modificar el comportamiento de partes de la aplicación. En este escenario, he estado usando una
with
cláusula para evitar que su código modifique cualquier cosa fuera del alcance con el que quiero que jueguen. La parte (simplificada) del código que uso para hacer esto es:Este código asegura (de alguna manera) que el código definido por el usuario no tiene acceso a ningún objeto con alcance global, como
window
tampoco a ninguna de mis variables locales a través de un cierre.Solo como una palabra para el sabio, todavía tengo que realizar comprobaciones de código estático en el código enviado por el usuario para asegurarme de que no estén usando otras maneras furtivas para acceder al alcance global. Por ejemplo, el siguiente código definido por el usuario toma acceso directo a
window
:fuente
Mi
se reduce a
¿Puedes confiar en un código de tan baja calidad? No, vemos que se hizo absolutamente ilegible. Sin lugar a dudas, este ejemplo demuestra que no hay necesidad de declaración con, si estoy tomando la legibilidad correctamente;)
fuente