En primer lugar, quiero aclarar, sé que withestá en desuso , y usarlo generalmente es una mala práctica .
Sin embargo, mi pregunta es sobre un caso especial: usar un Proxyobjeto especial como parámetro de with.
Antecedentes
Estoy trabajando en un proyecto, donde tengo que limitar el acceso de un código al alcance global.
Un enfoque podría ser usar un bucle con eval, que crea variables constantes con el valor de undefinedpara cada propiedad del objeto global, pero eso parece aún peor que usar with, y no puede limitar el acceso a las variables creadas con lety const.
La idea
La idea es utilizar a Proxycomo argumento de with, cuyo ...
hastrap siempre regresatrue, por lo tanto, no permite que ninguna búsqueda o tarea vaya más allá de lawithdeclaracióngettrap funciona normalmente, excepto que arrojanReferenceErrors cuando intentan acceder a una variable no existente (es decir, propiedad)setla trampa funciona normalmente (o puede contener alguna lógica personalizada)targetel objeto no tiene[[Prototype]](es decir, se creó conObject.create(null))targetEl objeto tiene una@@unscopablespropiedad, con el valor de un objeto vacío, para permitir el alcance de cada propiedad
Entonces, algo como este código:
const scope = Object.create(null)
Object.assign(scope, {
undefined,
console,
String,
Number,
Boolean,
Array,
Object,
/* etc. */
[Symbol.unscopables]: Object.create(null)
})
const scopeProxy = new Proxy(scope, {
get: (obj, prop) => {
if (prop in obj)
return obj[prop]
else
throw new ReferenceError(`${prop} is not defined`)
},
set: Reflect.set,
has: () => true
})
with(scopeProxy) {
//Sandboxed code
foo = Number('42')
console.log(foo) //42
try{
console.log(scopeProxy) //Inaccessible
}catch(e){
console.error(e) //ReferenceError: scopeProxy is not defined
}
}
Evitar contras
Hay varias contras enumeradas en la página de MDN sobre la withdeclaración , pero este uso elimina todas.
1. Rendimiento
El problema:
Buscar identificadores que no sean miembros del
withobjeto de parámetro de la declaración es menos eficaz.Evitación:
Ninguna búsqueda puede ir más allá del objeto de parámetro.
2. Ambigüedad
El problema:
Es difícil decidir qué identificador se busca de aquellos con el mismo nombre.
Evitación:
Todas las búsquedas y asignaciones recuperan o modifican la propiedad del objeto de parámetro.
3. compatibilidad hacia adelante
El problema:
Las propiedades de los objetos de parámetros o sus prototipos pueden cambiar en el futuro.
Evitación:
El objeto de parámetro está inicialmente vacío y no tiene prototipo, por lo tanto, ninguna propiedad puede cambiar.
Pregunta
El código anterior funciona perfectamente, y los contras enumerados en MDN no se aplican a esto.
Entonces, mi pregunta es:
¿Sigue siendo una mala práctica usar la withdeclaración, y si es así, cuáles son las desventajas de usarla en este caso?

withesta manera es malo o no.withun proxy todavía es bastante lento. Intentaría buscar una solución diferente para el problema subyacente, pero aparte de eso, solo lo está utilizandowithcomo una herramienta que parece hacer lo que necesita.Respuestas:
Suena como el viejo tema de alcance léxico vs dinámico . En general, el alcance léxico es más seguro, pero en algunas situaciones el alcance dinámico tiene sentido, ya que simplifica mucho algunas soluciones. Diría que su ejemplo es uno de los casos, donde puede ser útil.
fuente