まず第一に、明確にしたいのですが、これwith
は非推奨であり、それを使用することは一般的に悪い習慣です。
しかし、私の質問は特別なケースについてです:Proxy
のパラメーターとして特別なオブジェクトを使用しますwith
。
バックグラウンド
私はプロジェクトに取り組んでおり、コードへのアクセスをグローバルスコープに制限する必要があります。
一つのアプローチは、ループを使用するのが良いかもしれないeval
の値で一定の変数を作成している、undefined
グローバルオブジェクトのプロパティごとに、しかし使用するよりもさらに悪い思われるwith
、として作成した変数へのアクセスを制限することはできませんlet
とconst
。
アイデア
のアイデアはProxy
、の引数としてaを使用するwith
ことです...
has
trapは常にを返す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
ステートメントを使用することは依然として悪い習慣ですか?その場合、この場合にステートメントを使用することの欠点は何ですか?
with
この方法の使用が悪いかどうかです。
with
。また、プロキシを介したプロパティへのアクセスは依然として非常に遅くなります。根本的な問題に対する別の解決策を探してみますが、それ以外は、with
必要なことを行うように見えるツールとして使用しているだけです。