Antes de tudo, quero esclarecer, sei que isso withfoi preterido e usá-lo geralmente é uma prática ruim .
No entanto, minha pergunta é sobre um caso especial: usar um Proxyobjeto especial como parâmetro de with.
fundo
Estou trabalhando em um projeto, no qual tenho que limitar o acesso de um pedaço de código ao escopo global.
Uma abordagem pode ser usar um loop com eval, que cria variáveis constantes com o valor de undefinedpara cada propriedade do objeto global, mas isso parece ainda pior do que usar withe não pode limitar o acesso a variáveis criadas com lete const.
A ideia
A idéia é usar a Proxycomo argumento de with, cuja ...
hasA armadilha sempre retornatrue, portanto, não permite que nenhuma pesquisa ou atribuição vá além dawithinstruçãogetA armadilha opera normalmente, exceto que eles lançamReferenceErrors ao tentar acessar uma variável inexistente (ou seja, propriedade)seta armadilha opera normalmente (ou talvez contenha alguma lógica personalizada)targetO objeto não possui[[Prototype]](ou seja, foi criado comObject.create(null))targetO objeto tem uma@@unscopablespropriedade, com o valor de um objeto vazio, para permitir o escopo de cada propriedade
Então, 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
}
}
Evitando contras
Existem vários contras listados na página do MDN sobre a withdeclaração , mas esse uso se livra de cada uma.
1. Desempenho
O problema:
A pesquisa de identificadores que não são membros do
withobjeto de parâmetro da instrução tem menos desempenho.Prevenção:
Nenhuma pesquisa pode ir além do objeto de parâmetro.
2. Ambiguidade
O problema:
É difícil decidir qual identificador é procurado por pessoas com o mesmo nome.
Prevenção:
Todas as pesquisas e atribuições recuperam ou modificam a propriedade do objeto de parâmetro.
3. Compatibilidade futura
O problema:
As propriedades dos objetos de parâmetro ou seus protótipos podem mudar no futuro.
Prevenção:
O objeto de parâmetro está inicialmente vazio e não possui protótipo; portanto, nenhuma propriedade pode ser alterada.
Questão
O código acima funciona perfeitamente e os contras listados no MDN não se aplicam a isso.
Então, minha pergunta é:
Ainda é uma má prática usar a withdeclaração e, em caso afirmativo, quais são as desvantagens de usá-la nesse caso?
withdessa maneira é ruim ou não.
withum proxy ainda é bastante lento. Eu tentaria procurar uma solução diferente para o problema subjacente, mas fora isso, você está apenas usando withcomo uma ferramenta que parece fazer o que você precisa.