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