Является ли использование оператора with с прокси плохой практикой? - PullRequest
8 голосов
/ 05 января 2020

Прежде всего, Я хочу уточнить, я знаю, что 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 все еще плохой практикой * утверждение, и если да, то каковы недостатки использования его в этом случае?

1 Ответ

1 голос
/ 05 января 2020

Звучит как старый добрый лексический против динамического c сфера действия топи c. В целом, лексическая область видимости более безопасна, но в некоторых ситуациях динамическая область видимости имеет смысл, поскольку она значительно упрощает некоторые решения. Я бы сказал, что ваш пример - один из случаев, когда он может быть полезен.

...