プロキシで「with」ステートメントを使用することは悪い習慣ですか?


8

まず第一に、明確にしたいのですが、これwithは非推奨であり、それを使用すること一般的に悪い習慣です。

しかし、私の質問は特別なケースについてです:Proxyのパラメーターとして特別なオブジェクトを使用しますwith


バックグラウンド

私はプロジェクトに取り組んでおり、コードへのアクセスをグローバルスコープに制限する必要があります。

一つのアプローチは、ループを使用するのが良いかもしれないevalの値で一定の変数を作成している、undefinedグローバルオブジェクトのプロパティごとに、しかし使用するよりもさらに悪い思われるwith、として作成した変数へのアクセスを制限することはできませんletconst

アイデア

のアイデアはProxy、の引数としてaを使用するwithことです...

  • hastrapは常にを返すtrueので、withステートメントを超えて検索や割り当てを行うことはできません
  • getトラップは正常に動作しますが、ReferenceError存在しない変数(プロパティ)にアクセスしようとするとs がスローされます。
  • set トラップは正常に動作します(またはカスタムロジックが含まれている可能性があります)
  • 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ステートメントのパラメーターオブジェクトのメンバーではない識別子を検索すると、パフォーマンスが低下します。

  • 回避:

    ルックアップは、パラメーターオブジェクトを超えることはできません。

2.あいまいさ

  • 問題:

    同じ名前のIDからどの識別子を検索するかを決めるのは困難です。

  • 回避:

    すべてのルックアップと割り当ては、パラメーターオブジェクトのプロパティを取得または変更します。

3.上位互換性

  • 問題:

    パラメータオブジェクトのプロパティまたはそのプロトタイプは、将来変更される可能性があります。

  • 回避:

    パラメータオブジェクトは最初は空でプロトタイプがないため、プロパティを変更できません。

質問

上記のコードは完全に機能し、MDNにリストされているコントラはこれには適用されません。

だから、私の質問は:

withステートメントを使用することは依然として悪い習慣ですか?その場合、この場合にステートメントを使用することの欠点は何ですか?


サンドボックス内でコードを実行することが実際に必要なようです。はい、サンドボックスはその実装でプロキシを使用する可能性がありますが、おそらくこれを自分で書くべきではありません。
ベルジ

@Bergi知っています。サンドボックスのメカニズムはこれよりも複雑であるべきですが、私の質問は、このサンドボックスが安全で優れているかどうかではなく、withこの方法の使用が悪いかどうかです。
FZ

ええと、それでも厳密モードを使用することはできませんwith。また、プロキシを介したプロパティへのアクセスは依然として非常に遅くなります。根本的な問題に対する別の解決策を探してみますが、それ以外は、with必要なことを行うように見えるツールとして使用しているだけです。
ベルギ

回答:


1

古き良き語彙対動的スコープのトピックのように聞こえます。一般に、レキシカルスコープの方が安全ですが、一部のソリューションを非常に単純化するため、状況によってはダイナミックスコープが理にかなっています。あなたの例は、それが役に立つかもしれないケースの1つだと思います。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.