Прежде всего, Я хочу уточнить, я знаю, что with
устарело , и его использование обычно плохая практика .
Однако мой вопрос касается особого случая: использование специального объекта Proxy
в качестве параметра with
.
Справочная информация
Я работаю над проектом, в котором я должен ограничить доступ к коду кода для глобальной области видимости.
Одним из подходов может быть использование al oop с eval
, которое создает постоянные переменные со значением undefined
для каждого свойства глобального объекта, но это выглядит даже хуже, чем при использовании with
и не может ограничивать доступ к переменным, созданным с помощью let
и const
.
Идея
Идея состоит в использовании Proxy
в качестве аргумента with
, чья ...
has
ловушка всегда возвращает true
, поэтому она не разрешает поиск или присвоение go за пределами with
оператор get
trap-сообщения работают нормально, за исключением того, что они выдают ReferenceError
s при попытке доступа к несуществующей переменной (т. Е. Свойству) set
trap-сообщения работают нормально ( или может содержать некоторые пользовательские логики c) target
объект не имеет [[Prototype]]
(т. е. он был создан с помощью Object.create(null)
) target
объект имеет @@unscopables
свойство, со значением пустого объекта, для разрешения области видимости каждого свойства
Итак, что-то вроде этот код:
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
}
}
Предотвращение контрас
На странице MDN перечислены несколько контрас о выражении with
, но это его использование избавляется от каждого.
1. Производительность
Проблема:
Поиск идентификаторов, не являющихся членами объекта параметра оператора with
, менее производительный.
Избежание:
Поиск не может go за пределами объекта параметра.
2. Неоднозначность
Проблема:
Трудно решить, какой идентификатор будет найден среди людей с тем же именем.
Избежание:
Все поиски и назначения извлекают или изменяют свойство объекта параметра.
3. Прямая совместимость
Проблема:
Свойства объектов параметров или их прототипы могут измениться в будущем.
Избегание :
Объект параметра изначально пуст и не имеет прототипа, поэтому свойства не могут быть изменены.
Вопрос
Приведенный выше код работает отлично, и Контры, перечисленные в MDN, к этому не относятся.
Итак, мой вопрос:
Является ли использование with
* 1141 все еще плохой практикой * утверждение, и если да, то каковы недостатки использования его в этом случае?