序文
この質問には難しい解決策がありますが、この質問をしたときにインタビュアーが本当に調べたいのは、暗黙の変換の知識ポイントの理解と、データの乗っ取りを検討できるかどうかです。
トリッキーな解決策
let i=1;
with({
get a() {
return i++;
}
}){
if(a==1 && a==2 && a==3) {
console.log('哈哈哈,成功了');
}
}
暗黙の変換
jsで==
2つの値を比較する場合、次の操作が実行されます:
- 2つの比較された値を同じタイプに変換します
- 変換後(方程式の片側または両側が変換される場合があります)、値の比較が実行されます
最終的な比較方法は===
、等式演算子の比較方法と同等であり、等式演算子は可換法則を満たしています。
等式演算子は、次の図に示すように、さまざまなタイプの値を比較します。
表から取得できる情報のポイントがいくつかあります(a == 1)
。a
- aはタイプ
String
であり、数値に変換可能です1('1' == 1 => true)
- aはタイプ
Boolean
であり、数値に変換可能です1 (true == 1 => true)
- aのタイプは
Object
、変換メカニズムを通過した後、数値1に変換できます(以下を参照)。
オブジェクトのプリミティブ型への「変換メカニズム」
ルール1および2については、特別なことは何もありません。3を見てみましょう。
オブジェクトがプリミティブ型に変換されると、組み込み[ToPrimitive]
関数が呼び出されます。ロジックはおおよそ次のとおりです。 :
- メソッドがある場合は、
Symbol.toPrimitive
最初にそれを呼び出してから戻ります。それ以外の場合は2に進みます。 - 呼び出し
valueOf
、プリミティブ型に変換可能な場合は戻り、そうでない場合は3を実行します。 - を呼び出し
toString
、プリミティブ型に変換可能な場合は戻り、それ以外の場合は4を実行します。 - どちらも元のタイプを返さない場合、エラーが報告されます。
解決:
const a = {
i: 1,
[Symbol.toPrimitive]() {
return this.i++
}
}
// 每次进行a == xxx时都会先经过Symbol.toPrimitive函数,自然也就可以实现a依次递增的效果
if (a == 1 && a == 2 && a == 3) {
console.log('哈哈哈,成功了')
}
もちろんvalueOf
、toString
const a = {
i: 1,
valueOf() {
return this.i++
}
}
// 每次进行a == xxx时都会先经过valueOf/toString函数,自然也就可以实现a依次递增的效果
if (a == 1 && a == 2 && a == 3) {
console.log('哈哈哈,成功了')
}
データハイジャック
Object.defineProperty
、オブジェクトをハイジャックし、プロパティがwindow
読み取られるたびに1ずつインクリメントします。a
_a
Object.defineProperty(window, 'a', {
get() {
return _a++;
}
})
あなたがそれを考えることができれば、defineProperty
あなたは自然にそれを考えるでしょうproxy
let a = new Proxy({
i:1}, {
get(target){
console.log(target);
return () => target.i++
}
})
3つの方法、あなたはそれを学びましたか?