(a == 1 && a == 2 && a == 3)は真と評価できますか?


2484

モデレーターへのメモ:コードを編集したい、またはこの通知を削除したいという衝動に抵抗してください。空白のパターンは問題の一部である可能性があるため、不必要に改ざんしないでください。「ホワイトスペースは重要ではない」陣営にいる場合は、コードをそのまま受け入れることができるはずです。

JavaScriptで(a== 1 && a ==2 && a==3)評価できる可能性trueはありますか?

大手テック企業からのインタビューです。それは2週間前に起こりましたが、私はまだ答えを見つけようとしています。日々の仕事でそのようなコードを書くことは決してないことは知っていますが、私は興味があります。


9
コメントは詳細な議論のためのものではありません。この会話はチャットに移動しました
だます

109
明らかにこれを広すぎると締めくくるように投票した人々に:それは有効な答えが多すぎると言っている、Javascriptの発掘ですか?
tomsmeding

24
一部の人々は、何が可能であるかについて哲学的に座っています。他の企業は、クライアントのために実行可能なビジネスに適した製品を構築しているかどうかに注力しています。IMO、この質問は、面接でこれらの種類の質問をしたり、この種類のコードを記述したりしてはならないという事実を除いて、実用的な有用性はありません。それが閉じられるべき理由です。つまり、企業は誰かが本当のお金を払って周りに座ってこのことについて話し合っていることに気付いていますか?
P.Brian.Mackey 2018年

15
答えを読んだ後、話の教訓は次のとおりです。つまり、「ASCII以外の変数名を禁止するコーディング標準を使用し、前の2つの教訓を適用するリンティングプロセスを使用==すること」です===
ジェシーC.スライサー

87
モデレーターのメモ: Stack Overflowには、問題の言語に対するさまざまな言語での回答で人々が口を揃えてきた歴史があります。これら、異なる言語ではありますが、一般的な問題の解決策であるため、質問に答えようとする試みです。「回答なし」のフラグを立てないでください。そうは言っても、別の言語での回答の投稿を控えてください-この質問がJavaScriptに固有である理由があります。これらの他の回答のいくつかのコメントで指摘されているように、言語固有の質問が好きな理由がありますそのままです。
BoltClock

回答:


3323

あなたはを活用する場合はどのよう==な作品は、単にカスタムオブジェクトと作成することができますtoString(またはvalueOf、それはそれはそれはそれを満たすすべての3つの条件などに使用されるたびに返すどのような変更)機能を。

const a = {
  i: 1,
  toString: function () {
    return a.i++;
  }
}

if(a == 1 && a == 2 && a == 3) {
  console.log('Hello World!');
}


これが機能する理由は、緩い等価演算子の使用によるものです。緩やかな等式を使用する場合、オペランドの1つが他と異なるタイプである場合、エンジンは1つをもう1つに変換しようとします。左側のオブジェクトと右側の数値のvalueOf場合、最初に呼び出し可能かどうかを呼び出し、それが失敗するとを呼び出して、オブジェクトを数値に変換しようとしますtoString。私toStringがこの場合に使用したのは、それが頭に浮かんだものだからvalueOfこそ、より理にかなっています。代わりにから文字列を返した場合toString、エンジンは文字列を数値に変換しようとしましたが、パスが少し長くなりますが、同じ最終結果が得られます。


70
暗黙のvalueOf()操作を変更してこれを達成できますか?
スターリングアーチャー

43
はい。同じ理由で、valueOfはtoStringの代わりに機能します
Kevin B

4
コメントは詳細な議論のためのものではありません。この会話はチャットに移動しました
だます

13
よれば、この数変換は第1の試みであろうvalueOfわずかに良好です。
Salman A

6
@Pureferret等価比較の左側はオブジェクトではなく、数値です。そのオブジェクトに数値プロパティがあるiことは、エンジンを気にしません。;)
tomsmeding 2018年

2057

私は抵抗できませんでした-他の答えは間違いなく真実ですが、実際には次のコードを通り過ぎることはできません。

var a = 1;
var a = 2;
var a = 3;
if(aᅠ==1 && a== 2 &&ᅠa==3) {
    console.log("Why hello there!")
}

if(私があなたの質問からコピーした)ステートメントの奇妙な間隔に注意してください。これは、ECMAスクリプトによってスペース文字として解釈されないUnicodeの空白文字である半角ハングル(慣れていない人のための韓国語)です。これは、識別子の有効な文字であることを意味します。したがって、3つの完全に異なる変数があります。1つはaの後にハングル、もう1つは前に、最後の1つはaだけです。_読みやすくするためにスペースを置き換えると、同じコードは次のようになります。

var a_ = 1;
var a = 2;
var _a = 3;
if(a_==1 && a== 2 &&_a==3) {
    console.log("Why hello there!")
}

Mathiasの変数名バリデーターの検証を確認しください。その奇妙な間隔が実際に彼らの質問に含まれていたなら、私はそれがこの種の答えのヒントであると確信しています。

これを行わないでください。真剣に。

編集:(変数の開始は許可されていませんが)ゼロ幅のジョイナー文字とゼロ幅の非ジョイナー文字も変数名で許可されていることに注意してください- ゼロ幅文字によるJavaScriptの難読化を参照してください-賛否両論?

これは次のようになります。

var a= 1;
var a‍= 2; //one zero-width character
var a‍‍= 3; //two zero-width characters (or you can use the other one)
if(a==1&&a‍==2&&a‍‍==3) {
    console.log("Why hello there!")
}


368
元の質問の奇数の間隔から判断すると、これは、インタビューの質問が探していたまさにその答えだと思います-スペースのように見える非スペース文字を悪用します。良いスポット!
バラカス2018年

18
@Baracusこの(ひどい)テクニックを思い出させたのは、ケビンの答えについてのコメントの奇妙な間隔に気付いたのはRonJohnでした。でも、ブログの投稿があったために数年前に私の仕事を回っていたので、誰もこれについてまだ答えていなかったので、ちょっと驚きました。
Jeff

102
もちろん、これは標準の抜け穴として禁止されており、これはインタビューにも当てはまります。[引用が必要]
Sanchises

13
元の間隔を考慮すると、さらに悪い可能性がありvar ᅠ2 = 3ます。つまり、変数が使用されています。その三つの変数がありますaᅠᅠ= 1, ᅠ2 = 3, a = 3a␣ = 1, ␣2 = 3, a = 3そのため、(a␣==1 && a==␣2 && a==3)...)
ホルガー

2
@ AL-zami 2つの変数に余分な文字があり、画面ではスペースとして表示されますが、識別子の一部として解釈されます。つまり、a、a、aという 3つの別々の変数があります。余分な文字はハングル半角スペ​​ース。
Jeff

620

可能です!

var i = 0;

with({
  get a() {
    return ++i;
  }
}) {
  if (a == 1 && a == 2 && a == 3)
    console.log("wohoo");
}

これは、withステートメント内でゲッターを使用して、a3つの異なる値に評価させます。

...これは、これが実際のコードで使用されるべきであるという意味ではありません...

さらに悪いことに、このトリックはの使用でも機能します===

  var i = 0;

  with({
    get a() {
      return ++i;
    }
  }) {
    if (a !== a)
      console.log("yep, this is printed.");
  }


65
はい、私は同じことを試していました:)したがって、インタビューでの正解は、「使用しないのでコードで発生することはないwith」です。
2018年

7
@Pointy-そして、with許可されていない厳密モードでプログラムします。
jfriend00

6
@Pointyは、受け入れられた回答で同様のことをしているwithため、それが発生する可能性があります
Jungkook

2
@jorrit誰も使用しません==。そして===、受け入れられた回答を防ぎます
ジョナスウィルムス

4
@JonasW。多くの人がまだ使用して==いますが、それwith以来私は見ていません...実際には、JSのドキュメントの「それを使用しないでください」の外側には決していません。とにかく、素晴らしいソリューション。
ワートワート

516

ゲッターまたはvalueOfなしの例:

a = [1,2,3];
a.join = a.shift;
console.log(a == 1 && a == 2 && a == 3);

これは、配列を==呼び出すtoStringを呼び出すため機能します.join

Symbol.toPrimitiveES6と同等の使用する別のソリューションtoString/valueOf

let i = 0;
let a = { [Symbol.toPrimitive]: () => ++i };

console.log(a == 1 && a == 2 && a == 3);


9
without valueOf、まあ...もっと間接的ですが、基本的に同じことです。
Jonas Wilms、

11
オブジェクト自体の結合関数以外は何もオーバーライドせず、ロジックを真に評価させる非常にクリーンで読みやすいハックであるため、私はこのソリューションが本当に好きです。
Alex Pedersen、

28
正直なところ、これが最良の答えだと思います。通常のことではなく、いくつかの値を設定するだけです。JSの基本的な知識があっても非常に理解しやすいです。よくやった。
Zac Delventhal

14
これは非常に理にかなっていて、ほとんど便利だと感じています。
Andrew

7
私はほとんどの答えが悪用についても知っていたtoStringvalueOfが、この1は完全にガードの私をつかまえました。とても賢く、私はそれが.join内部で呼び出されることを知りませんでしたが、それは完全に理にかなっています。
GBarroso

268

可能かどうかを尋ねられた場合(必須ではない)、乱数を返すように「a」に要求できます。1、2、3を順番に生成する場合はtrueです。

with({
  get a() {
    return Math.floor(Math.random()*4);
  }
}){
  for(var i=0;i<1000;i++){
    if (a == 1 && a == 2 && a == 3){
      console.log("after " + (i+1) + " trials, it becomes true finally!!!");
      break;
    }
  }
}


102
他の解決策を知っていたとしても、私は故意にこの答えを出します。なぜならそれは質問に答えますが、明らかに彼らが求めていたものではないからです。愚かなゲームをプレイし、愚かな賞品を獲得してください。
ESR

2
しかし、1000回以上の試行が必要な場合はどうでしょうか。
Piyin

9
@Piyin 1000回以上のトライアルが必要な場合は、賞品を獲得できます!
スキート、

5
この答えのように、私は極端にそれを取ることは、これがで可能であることを示唆しているので、任意のプログラムが実行されている間、CPUのレジスタは/十分な宇宙線で打撃を受けるキャッシュ場合、言語、または1つは、故意に故障枝のよう電源グリッチを実行する場合if条件式は実際にはジャンプしません。
Ponkadoodle 2018年

最低:1、最高:412
KyleFairns

210

正規表現なしでは何もできない場合:

var a = {
  r: /\d/g, 
  valueOf: function(){
    return this.r.exec(123)[0]
  }
}

if (a == 1 && a == 2 && a == 3) {
    console.log("!")
}

valueOfObjectがプリミティブ(Numberなど)と比較されるときに呼び出されるカスタムメソッドのために機能します。主なトリックは、フラグ付きの正規表現をa.valueOf呼び出すため、毎回新しい値を返すことです。これにより、一致が見つかるたびにその正規表現が更新されます。したがって、最初は一致して更新されます。なので、次回は正規表現が一致します。execglastIndexthis.r.lastIndex == 01lastIndexthis.r.lastIndex == 12


22
@Abdillah正規表現オブジェクトは、一致する最後のインデックスを記憶し、execもう一度呼び出すと、そのインデックスから検索を開始します。MDNは明確ではありません。
Simon Chan

わかりましたので、this.r正規表現オブジェクトは状態/インデックスを覚えています。ありがとう!
Abdillah

execただし、文字列化する整数ではなく、文字列を渡すことをお勧めします。
ベルギ

正規表現を使用すると、2つの問題が発生します
Aleksey Solovey

191

これは、グローバルスコープで次を使用して実現できます。以下のためのnodejs使用globalの代わりに、window以下のコードインチ

var val = 0;
Object.defineProperty(window, 'a', {
  get: function() {
    return ++val;
  }
});
if (a == 1 && a == 2 && a == 3) {
  console.log('yay');
}

この回答は、変数を取得するゲッターを定義することにより、実行コンテキストのグローバルスコープによって提供される暗黙的な変数を悪用します。


これaは、thisそうではないように見えるプロパティであると想定しています。Ifはa(それがどのように見える)ローカル変数だった、これは動作しません。
jfriend00

1
@ jfriend00は、var aを配置した場合を意味します。どこか?
jontro 2018年

うん。参照は、のプロパティではなく、どこかで変数であるa == 1ことを意味aしますthis。で変数を宣言両方が、一般的に、真の可能性グローバル、のような型破りな場所がある一方var aまたはlet a手段まったくありませんthisあなたがアクセスすることができますようaだコードが想定しているあなたのようなプロパティとして。したがって、あなたのコードは奇妙なグローバル変数を想定しているようです。たとえば、コードはnode.jsでは機能せず、関数内のstrictモードでは機能しません。それが機能する正確な状況を指定し、おそらくそれが機能する理由を説明する必要があります。そうでなければ、それは誤解を招くものです。
jfriend00

確かに@ jfriend00。それが他のすでに答えと組み合わせてはるかに多くの価値を加えるかどうかはわかりません。回答が更新されます
jontro、2018年

14
問題は、これが「いつでも」真実であるかどうかでした。そして答えはイエスです、そしてこれはそれが真であるかもしれないシナリオの1つです:aローカル変数ではなく、インクリメントするゲッターでグローバルスコープで定義されます。
Zac Delventhal

190

これはa、SharedArrayBufferといくつかのメインスクリプトを介して、たとえば2つのWebワーカーが変数にアクセスする場合に可能です。可能性は低いですが、コードはマシンコードにコンパイルされたときに、ウェブの労働者が変数を更新することも可能であるa条件ので、時間だけでa==1a==2そしてa==3満足しています。

これは、WebワーカーとJavaScriptのSharedArrayBufferによって提供されるマルチスレッド環境での競合状態の例になります。

上記の基本的な実装は次のとおりです。

main.js

// Main Thread

const worker = new Worker('worker.js')
const modifiers = [new Worker('modifier.js'), new Worker('modifier.js')] // Let's use 2 workers
const sab = new SharedArrayBuffer(1)

modifiers.forEach(m => m.postMessage(sab))
worker.postMessage(sab)

worker.js

let array

Object.defineProperty(self, 'a', {
  get() {
    return array[0]
  }
});

addEventListener('message', ({data}) => {
    array = new Uint8Array(data)
    let count = 0
    do {
        var res = a == 1 && a == 2 && a == 3
        ++count
    } while(res == false) // just for clarity. !res is fine
    console.log(`It happened after ${count} iterations`)
    console.log('You should\'ve never seen this')
})

modifier.js

addEventListener('message' , ({data}) => {
    setInterval( () => {
        new Uint8Array(data)[0] = Math.floor(Math.random()*3) + 1
    })
})

私のMacBook Airでは、それは最初の試みでおよそ100億回の繰り返しの後に起こります:

ここに画像の説明を入力してください

2回目の試み:

ここに画像の説明を入力してください

言ったように、可能性は低くなりますが、十分な時間が与えられれば、それは条件にヒットします。

ヒント:システムで時間がかかりすぎる場合。のみa == 1 && a == 2を試してに変更Math.random()*3してくださいMath.random()*2。リストにどんどん追加すると、ヒットする可能性が低くなります。


50
正直なところ、これが最良の答えです。他のすべての答えは、非常に直感的でない何かを行うための意図的な試みを必要とします。この答えは実際には、現実の世界で発生する可能性のあるもの、つまり競合状態を反映しています。
トム渦巻き模様の

34
それだけでなく、実際にこれが現実の世界で起こるのを見てきました。問題の正確な条件ではなく、関数の開始時に(a == 1)をチェックし、関数の後半で(a == 2)をチェックして、コードが両方の条件にヒットしたことを確認します。ちなみに、これが最初に発生したのは自動車のエンジンコントローラでした。コーディング標準を導入しました。2回目は軍用機用のチャフおよびフレアディスペンサーシステムでした。会社での最初の日にこれを見つけて修正しましたが、チームの残りのメンバーはまだ問題について話していました。(評価レベル:高!:)
グラハム

38
それで、あなたは「車のエンジンコントローラー」と「チャフとフレアのディスペンサーシステム」に取り組んでいます。もう外に出ようとは思わない。
psaxton、

12
@psaxton :)もちろんそうではありませんが、共有データを持つマルチスレッドソフトウェアがあります。これは、JavascriptやWebワーカーに固有ではなく、すべてのマルチスレッドソフトウェアのアンチパターンです。アセンブリ言語、Brainf * ck、Visual BASIC、C、Javascriptのいずれでプログラミングしているかは関係ありません。マルチスレッドアプリケーションで共有データを使用してこれを行うと、常に失敗します。
グラハム、

4
これは、@ jontroの回答の精巧なラッパーになっていると思います。
qntm 2018年

148

これは、一連の自己上書きゲッターを使用して行うこともできます。

(これはjontroのソリューションに似ていますが、カウンター変数を必要としません。)

(() => {
    "use strict";
    Object.defineProperty(this, "a", {
        "get": () => {
            Object.defineProperty(this, "a", {
                "get": () => {
                    Object.defineProperty(this, "a", {
                        "get": () => {
                            return 3;
                        }
                    });
                    return 2;
                },
                configurable: true
            });
            return 1;
        },
        configurable: true
    });
    if (a == 1 && a == 2 && a == 3) {
        document.body.append("Yes, it’s possible.");
    }
})();


61
ゲッターを使用するアプローチは===、だけでなくでも機能することに注意してください==
マキエン

このソリューションはthis、arrow関数の本体内のグローバルオブジェクトであることに依存しています。
ロイティンカー

@Midnightas他の回答は「ピラミッドコード」として分類しません。
Patrick Roberts

これは任意の順序でも機能することに注意してください。のように(a == 3 && a == 2 && a == 1)
ヨハネス

131

または、クラスとチェックのインスタンスを使用することもできます。

function A() {
    var value = 0;
    this.valueOf = function () { return ++value; };
}

var a = new A;

if (a == 1 && a == 2 && a == 3) {
    console.log('bingo!');
}

編集する

ES6クラスを使用すると、次のようになります。

class A {
  constructor() {
    this.value = 0;
    this.valueOf();
  }
  valueOf() {
    return this.value++;
  };
}

let a = new A;

if (a == 1 && a == 2 && a == 3) {
  console.log('bingo!');
}


5
function A() {value = 0;最初だけ?
Dave C

valueOf上書きされている、this method is usually called automatically by JavaScript behind the scenes, and not explicitly in code我々は値を比較したときにそれは実際に...インクリメント
Danyal Sandeelo

130

この回答はすでに投稿されていないので、これもミックスに投入します。これは、半角のハングルスペースに関するジェフの回答に似ています。

var a = 1;
var  = 2;
var а = 3;
if(a == 1 &&  == 2 && а == 3) {
    console.log("Why hello there!")
}

2番目のものとはわずかな違いに気付くかもしれませんが、最初と3番目は肉眼と同じです。3つすべてが異なる文字です。

a-ラテン小文字A-
全角ラテン小文字A-
аキリル文字小文字A

これの総称は「ホモグリフ」です。同じように見える異なるUnicode文字です。通常、まったく区別がつかない3つを取得することは困難ですが、場合によってはラッキーになることもあります。A、Αは、А、およびᎪは良く機能するであろう(ラテン-Aは、ギリシャのアルファキリル-A 、およびチェロキー-A ;それぞれ、残念ながらギリシャとチェロキー小文字はラテン語からあまりにも異なっているaα、およびdoesnのように上記のスニペットでは役に立ちません)。

ホモグリフ攻撃のクラス全体があり、最も一般的には偽のドメイン名(たとえばwikipediа.org(キリル文字)対wikipedia.org(ラテン文字))ですが、コードにも表示される可能性があります。通常、アンダーハンドであると呼ばれます(コメントで述べたように、[アンダーハンド]の質問はPPCGではトピックから外れていますが、以前はこの種の問題が発生するタイプの課題でした)。私が使用し、このウェブサイトを、この答えに使用homoglyphsを見つけること。


19
「わずかな食い違い」は私がそれを呼ぶ方法ではありません。

4
@hvdフォントのレンダリングに完全に依存します。これが見える
Draco18sは、

1
@Jakeええ、全角ラテン小文字Aは最大の同形異字ではありません(ただし、大文字の異体字は驚くべきものです)。一般に、必要な効果を得るには2つしか必要ありません。
Draco18sは、

@ Draco18s同意済み:通常は2つだけ必要です。追加情報もお見事!
JakeSteam

10
ユニコードバリアントセレクター(U + FE00..U + FE0F)を使用することもできます。これらのいずれもありませんaa︀ a︁ a︂。矛盾を心配する必要はもうありません。
Salman A

108

はい、可能です!😎

»JavaScript

if‌=()=>!0;
var a = 9;

if‌(a==1 && a== 2 && a==3)
{
    document.write("<h1>Yes, it is possible!😎</h1>")
}

上記のコードは短いバージョンであり(コメントでの注記について@Forivinに感謝)、次のコードはオリジナルです。

var a = 9;

if‌(a==1 && a== 2 && a==3)
{
    //console.log("Yes, it is possible!😎")
    document.write("<h1>Yes, it is possible!😎</h1>")
}

//--------------------------------------------

function if‌(){return true;}

私のコードの上側だけを見てそれを実行するなら、WOWと言いますか?

だから私ははいと言うだけで十分だと思います、あなたに言った誰かにそれは可能です:何も不可能ではありません

トリック:if名前がに似た関数を作成するために、後に隠し文字を使用しましたif。JavaScriptではキーワードを上書きできないため、この方法を使用せざるを得ませんでした。それは偽物ifですが、この場合はうまくいきます!


» C#

また、C#バージョンを記述しましたプロパティ値のテクニックを増やします)。

static int _a;
public static int a => ++_a;

public static void Main()
{
    if(a==1 && a==2 && a==3)
    {
        Console.WriteLine("Yes, it is possible!😎");
    }
}

ライブデモ


56
Javascriptバージョンは人類に対する真の犯罪であり、これを行う能力は、国連の慣習により違法であるべきです。javacriptのすべての知識を世界から一掃する時期が来たと思います。
2018年

2
関数宣言はさらに短くなる可能性があります。if‌=()=>!0
Forivin、2018年

4
document.writeいったいなぜあなたは使用しましたか?それは答えの残りの部分に関係なく採用されない確実な方法です。
セルブルス2018年

3
@Cerbrus、ご連絡ありがとうございます。私は最初に回答を書きましたconsole.logが、それをdocument.writeに変更しました。実際には常にconsole.logコードで使用していますが、ここではStackOverflowコードスニペットボックスでユーザーにテキストを表示したいだけです。したがって、で生成されたメッセージよりも美しいメッセージを表示したかったのconsole.logです。Run Code Snippet私の回答と他の回答のボタンをクリックします。SOコードスニペットでhtmlとJSとCSSを使用できるようにしたので、それを自分の回答で使用して見栄えよくしたいと考えました。私はそれが否定的な副作用を持っておらず、私の答えを大きくしたり、納得させたりしなかったと思います。
RAM

1
@Clearer、国連条約が世界を効果的に変えることができるなら、私たちはこれよりも良い世界を持っているはずです。私たちは国連での声明以上のものを必要としています。その日まで、私はこのJavascriptのトリックを使うことができると思います;)
RAM

97

JavaScript

a == a +1

JavaScriptでは、整数はなくNumber、s のみがあり、倍精度浮動小数点数として実装されます。

つまり、Number aが十分に大きければ、3つの連続した整数に等しいと見なすことができます。

a = 100000000000000000
if (a == a+1 && a == a+2 && a == a+3){
  console.log("Precision loss!");
}

確かに、それはインタビュアーが尋ねたものとは完全には一致しません(それはで動作しませんa=0)が、非表示の関数や演算子のオーバーロードに関するトリックは含まれていません。

他の言語

参考までにa==1 && a==2 && a==3、RubyとPython にはソリューションがあります。わずかな変更で、Javaでも可能です。

ルビー

カスタム付き==

class A
  def ==(o)
    true
  end
end

a = A.new

if a == 1 && a == 2 && a == 3
  puts "Don't do this!"
end

または増加a

def a
  @a ||= 0
  @a += 1
end

if a == 1 && a == 2 && a == 3
  puts "Don't do this!"
end

パイソン

class A:
    def __eq__(self, who_cares):
        return True
a = A()

if a == 1 and a == 2 and a == 3:
    print("Don't do that!")

ジャワ

Java Integerキャッシュを変更することが可能です:

package stackoverflow;

import java.lang.reflect.Field;

public class IntegerMess
{
    public static void main(String[] args) throws Exception {
        Field valueField = Integer.class.getDeclaredField("value");
        valueField.setAccessible(true);
        valueField.setInt(1, valueField.getInt(42));
        valueField.setInt(2, valueField.getInt(42));
        valueField.setInt(3, valueField.getInt(42));
        valueField.setAccessible(false);

        Integer a = 42;

        if (a.equals(1) && a.equals(2) && a.equals(3)) {
            System.out.println("Bad idea.");
        }
    }
}

27
@cᴏʟᴅsᴘᴇᴇᴅ:Java、Javascript、potayto、potahto :)十分なJS回答がすでにあります。他の言語でどのように実行できるかを示し、JS開発者にいくつかのアイデアを与えることが興味深いと思いました。
エリックドゥミニル2018年

2
@cᴏʟᴅsᴘᴇᴇᴅ:JSの例で更新されました。
エリックドゥミニル2018年

1
Javaバージョンが動作しないInteger a = 42(または動作する)のはなぜですか?自動ボクシングを理解しているので、Integer a = 42; a == 1 && a == 2 && a == 3すべてのintをボックス化する必要があります。または、これは比較のためにボックスを解除しますか?
97年

@ CAD97:開梱が行わInteger == intれるようです。しかし、Integer#equals(int)強制的にオートボクシングを使用すると、機能します。コメントをありがとう!
エリックドゥミニル2018年

@StephanBijzitter:説明してください。私の知る限りNumbersでは、基本的にdoubles に似たJS だけがあります。それらは整数のように見え、整数のように使用できますが、それでも整数ではありません。私はn == n + 1Java / Python / C / Ruby / ...の整数には当てはまらないと思います
Eric Duminil

80

これは、@ Jeffの回答を逆にしたバージョンです。隠し文字(U + 115F、U + 1160、またはU + 3164)を使用して12やのような変数を作成します3

var  a = 1;
var 1 = a;
var 2 = a;
var 3 = a;
console.log( a ==ᅠ1 && a ==ᅠ2 && a ==ᅠ3 );

*その答えは、ゼロ幅の非結合子(U + 200C)とゼロ幅の結合子(U + 200D)を使用することで簡略化できます。これらの文字はどちらも識別子の内側では使用できますが、先頭では使用できません。

var a = 1;
var a = 2;
var a = 3;
console.log(a == 1 && a == 2 && a == 3);

/****
var a = 1;
var a\u200c = 2;
var a\u200d = 3;
console.log(a == 1 && a\u200c == 2 && a\u200d == 3);
****/

同じ考えを使用して、他のトリックも可能です。たとえば、Unicodeバリエーションセレクターを使用して、まったく同じように見える変数を作成します(a︀ = 1; a︁ = 2; a︀ == 1 && a︁ == 2; // true)。


75

インタビューのルール1。不可能とは決して言いません。

隠されたキャラクターの策略の必要はありません。

window.__defineGetter__( 'a', function(){
    if( typeof i !== 'number' ){
        // define i in the global namespace so that it's not lost after this function runs
        i = 0;
    }
    return ++i;
});

if( a == 1 && a == 2 && a == 3 ){
    alert( 'Oh dear, what have we done?' );
}


6
痛い。__defineGetter__は実際にはjs言語の一部ではなく、醜いバージョンのdefinePropertyです。typeofは関数ではなく、この宣言されていないものiはひどいものです。まだ40票の価値があるようです:/
ジョナスウィルムス

6
@JonasW。41賛成:-) developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…__defineGetter__で非推奨になっていることは承知していますが、FireFox v 57.0.4では明確に実行されるため、代わりにこれを表示することにしましたなぜなら、レガシーコードは本物であり、無視することができないからです。醜さに関係なく、私がした方法で宣言することはよく知られている/文書化された動作です。多分私はちょうどPCG気分だった¯\ _(ツ)_ / defineProperty()i
¯– MonkeyZeus

68

正直なところ、それが真と評価する方法があるかどうか(そして他の人が示しているように、複数の方法がある)かどうか、私が探している答えは、何百ものインタビューを行った人として言えば、何かに沿って:

「まあ、たぶん、すぐにはわからない奇妙な一連の状況下ではそうかもしれません...しかし、実際のコードでこれが発生した場合は、一般的なデバッグ手法を使用して、それがどのようにして何をしていたのかを理解しますその状況を回避するためにすぐにコードをリファクタリングします...しかし、より重要なことは、そもそも複雑なコードのまさにその定義であり、複雑なコードを書かないように努めるからです。

一部の面接担当者は、明らかに非常にトリッキーな質問であることを明らかにすることを怒らせると思いますが、特に論理的な考えでそれをバックアップでき、私の質問に答えることができる場合、私は意見を持っている開発者を気にしません。自分自身についての意味のある発言。


13
質問(またはすべてのインタビューの質問)は、問題について考える意思のある候補者、特にこのように「明らかに明白」な問題をテストすることです。彼らが答えを「知っている」と信じているために考えることを拒否する誰かは、良い採用ではありません。
Shammoo 2018年

5
@Don Hatchいいえ、彼らが誠意をもって答えた場合、特に他の人が示したような正しい答えを出した場合、私は彼らにペナルティを課しません...コードを書くかどうかは良い方法です。知識が豊富で「正しい」答えを見つけられることは、優れた開発者であることの一部にすぎません。「専門家」の開発者にとってはるかに重要なのは、多くの場合、能力の低い開発者によって理解され維持されるコードを書くことです。過度に賢い開発者は、無能な開発者IMEと同じくらい悪い人です。
フランクW.ザメッティ

16
これは質問の答えにはなりません。
TylerH 2018年

6
この回答についての悲しいことは、1repユーザーが昨日その回答をし、2つの反対票を得てこの質問を削除することです。
ジョナスウィルムス

8
@JohnColeman質問は、コードがどのように真と評価されるかを尋ねます。そもそもインタビュアーが質問を提案した理由は問わない。この回答は、尋ねられている質問に対処しようとするものではなく、面接官の目的が何であったかを推測する試みの「何をするか」バージョンに完全に焦点を当てています。それが尋ねられた質問であるならば、それはあまりにも広範になるでしょう。したがって、この回答はここまたはサイトのどこにも属していません。
TylerH 2018年

43

このようなインタビューの質問を受け取った場合(またはコードで同様に予期しない動作に気付いた場合)、一見すると不可能と思われる動作を引き起こす可能性のあるものについて考えてください。

  1. エンコーディング:この場合、あなたが見ている変数はあなたが思っているものではありません。これは、意図的にホモグリフまたはスペース文字を使用してUnicodeをいじって、変数の名前を別の名前のように見せる場合に発生する可能性がありますが、予期しないUnicodeコードを含むWebからコードをコピーして貼り付ける場合など、エンコードの問題が誤って発生する可能性もありますポイント(たとえば、コンテンツ管理システムがflUnicode 'LATIN SMALL LIGATURE FL'(U + FB02)で置き換えるなどの「自動フォーマット」を行ったため)。

  2. 競合状態競合状態が発生する可能性があります。つまり、開発者が予期した順序でコードが実行されない状況です。競合状態はマルチスレッドコードで発生することがよくありますが、複数スレッドは競合状態を可能にするための要件ではありません。非同期性で十分です(混乱しないでください。非同期は複数のスレッドが内部で使用されることを意味しません)。

    したがって、JavaScriptはシングルスレッドであるため、競合状態から解放されるわけではないことに注意してください。シンプルなシングルスレッドの、ただし非同期の例については、こちらをご覧ください。ただし、単一のステートメントのコンテキストでは、JavaScriptで競合状態をヒットするのはかなり困難です。

    複数のスレッドを使用できるため、WebワーカーでのJavaScriptは少し異なります。@mehulmptは、Webワーカーを使用した優れた概念実証を示しています。

  3. 副作用:等価比較演算の副作用(この例のように明白である必要はありませんが、多くの場合、副作用は非常に微妙です)。

我々は古典の一つを見ていないので、問題のこれらの種類は、多くのプログラミング言語だけでなく、JavaScriptで表示することができたJavaScript WTFsここ1

もちろん、インタビューの質問とここにあるサンプルはすべて非常に不自然に見えます。ただし、次の点に注意してください。

  • 副作用は非常に厄介なものになる可能性があり、適切に設計されたプログラムには不要な副作用がないはずです。
  • マルチスレッド化および変更可能な状態は問題になる可能性があります。
  • 文字エンコーディングと文字列処理を正しく行わないと、厄介なバグが発生する可能性があります。

1たとえば、副作用(明白な1)を示す全く異なるプログラミング言語(C#の)の例を見つけることができるここに


1
それから、質問はあまりにも広範になります。さまざまな言語がさまざまな程度の容易さでこれを実装できます。これはJS固有のQ&Aであるため、この質問は非常に注目を集めていますが、それは私の2cにすぎません。
cs95 2018年

1
原因はC#とJavaScriptが異なるため、この答えは正当ではありません。
エドウィン

3
@Edwin:原因はまったく同じです:見た目が似ているグリフまたはスペース文字、競合状態、または比較演算の副作用(後者は私の例に示されています)でUnicodeを操作しています。
Dirk Vollmar

2
@cᴏʟᴅsᴘᴇᴇᴅ:物事をより広い角度から見ると、実際の問題がわかりやすくなることがあります。
Dirk Vollmar

3
この回答に「メタ」的な方法でこの質問のタグを付けることができるといいのですが。上記のすべての回答を読んだ後、JSには多くの穴があるように感じましたが、一度にすべての回答を合計しました。私の意見では、これをすばらしいインタビューの質問(言語固有のタグが削除されている場合)にするような方法でそれを行いました。ブラボー!
KCE 2018年

41

次に、別のバリエーションを示します。配列を使用して、必要な値をポップします。

const a = {
  n: [3,2,1],
  toString: function () {
    return a.n.pop();
  }
}

if(a == 1 && a == 2 && a == 3) {
  console.log('Yes');
}


31

さて、ジェネレーターを使った別のハック:

const value = function* () {
  let i = 0;
  while(true) yield ++i;
}();

Object.defineProperty(this, 'a', {
  get() {
    return value.next().value;
  }
});

if (a === 1 && a === 2 && a === 3) {
  console.log('yo!');
}


あなたはハックと言いますが、これはジェネレーターのユースケースだと確信しています... :)(まあ、これはthisウィンドウオブジェクトであることに依存していることを除きます)
コーディG

29

プロキシの使用:

var a = new Proxy({ i: 0 }, {
    get: (target, name) => name === Symbol.toPrimitive ? () => ++target.i : target[name],
});
console.log(a == 1 && a == 2 && a == 3);

プロキシは基本的にターゲットオブジェクト(最初のパラメーター)のふりをしますが、ターゲットオブジェクトの操作(この場合は「プロパティの取得」操作)をインターセプトするため、デフォルトのオブジェクトの動作以外のことを行う機会があります。この場合、「数値を取得」アクションは、各数値と比較するためにそのタイプを強制するaときに呼び出され==ます。これは起こります:

  1. ターゲットオブジェクトを作成します。{ i: 0 }ここで、iプロパティはカウンターです
  2. ターゲットオブジェクトのプロキシを作成し、それを a
  3. a ==比較ごとに、aの型はプリミティブ値に強制されます
  4. この型強制はa[Symbol.toPrimitive]()内部での呼び出しを引き起こします
  5. プロキシa[Symbol.toPrimitive]は、「取得ハンドラ」を使用して関数を取得します。
  6. プロキシの「取得ハンドラ」は、取得されているプロパティがであることを確認します。Symbol.toPrimitiveこの場合、プロパティが増分され、ターゲットオブジェクトからカウンタが返されます++target.i。別のプロパティが取得されている場合、フォールバックしてデフォルトのプロパティ値を返します。target[name]

そう:

var a = ...; // a.valueOf == target.i == 0
a == 1 && // a == ++target.i == 1
a == 2 && // a == ++target.i == 2
a == 3    // a == ++target.i == 3

他のほとんどの回答と==同様に、厳密な等価チェック(===)はプロキシがインターセプトできる型強制を行わないため、これは緩やかな等価チェック()でのみ機能します。


2
ただし、これにプロキシを使用する意味はありませんSymbol.toPrimitive。オブジェクトで同じように定義すると、同様に機能します。
Ry-

27

実際、質問の最初の部分に対する答えは、すべてのプログラミング言語で「はい」です。たとえば、これはC / C ++の場合です。

#define a   (b++)
int b = 1;
if (a ==1 && a== 2 && a==3) {
    std::cout << "Yes, it's possible!" << std::endl;
} else {
    std::cout << "it's impossible!" << std::endl;
}

27
すべてのプログラミング言語でそれが可能であるとは思いません。たとえば、すべての言語にプリプロセッサがあるわけではありません。さらに言えば、すべての言語&&が論理的な「and」を使用するわけではありません。
キーストンプソン、

3
演算子のオーバーロードを使用するPythonC ++の両方で機能する方法を見つけました。
ドナルドダック

7
そして、リフレクションを使用して整数キャッシュを台無しにすることで、Javaでそれを行うことができます。
97年

7
その場所での変異をサポートしていない言語ではそれを行うことはできません。たとえば、haskellで比較できるものはありません
Jason Carr

4
問題は、C ++ではなくJavaScriptについてです。
すべての労働者は必須です

26

同じですが、異なりますが、同じです(複数回「テスト」できます):

const a = { valueOf: () => this.n = (this.n || 0) % 3 + 1}
    
if(a == 1 && a == 2 && a == 3) {
  console.log('Hello World!');
}

if(a == 1 && a == 2 && a == 3) {
  console.log('Hello World!');
}

私のアイデアは、Numberオブジェクトタイプの方程式のしくみから始まりました。


4
2回目も機能します。
Salman A

25

記号を利用するECMAScript 6の回答:

const a = {value: 1};
a[Symbol.toPrimitive] = function() { return this.value++ };
console.log((a == 1 && a == 2 && a == 3));

以下のため==の使用は、JavaScriptが強制になっているa第二オペランドに何かの近くに(123この場合)。しかし、JavaScriptはそれ自体で強制を計算しようとする前に、を呼び出そうとしますSymbol.toPrimitiveSymbol.toPrimitiveJavaScript を提供する場合、関数が返す値を使用します。そうでない場合、JavaScriptはを呼び出しますvalueOf


24

これはそれを実装するための最小限のコードだと思います:

i=0,a={valueOf:()=>++i}

if (a == 1 && a == 2 && a == 3) {
  console.log('Mind === Blown');
}

各呼び出しでvalueOfグローバル変数をインクリメントするカスタムでダミーオブジェクトを作成しiます。23キャラクター!


14

これは、definePropertyを使用して、副作用を引き起こすグローバル変数を提供しています!

var _a = 1

Object.defineProperty(this, "a", {
  "get": () => {
    return _a++;
  },
  configurable: true
});

console.log(a)
console.log(a)
console.log(a)


8
あなたはクロージャーを使用することができますaget: (a => () => ++a)(0),グローバルは必要ありません。
Nina Scholz

13
@NinaScholz確かに、ここでは悪い慣行について話している-ただ私にこれをさせてくれ:D
Ben Aubin

1

valueOfクラス宣言でオーバーライドすることにより、それを行うことができます:

class Thing {
    constructor() {
        this.value = 1;
    }

    valueOf() {
        return this.value++;
    }
}

const a = new Thing();

if(a == 1 && a == 2 && a == 3) {
    console.log(a);
}

発生するのはvalueOf、各比較演算子で呼び出されることです。最初のものに、a等しくなり1、第二に、a等しくなる2たびにので、などなどにとvalueOf呼ばれる、の値がaインクリメントされます。

したがって、console.logが起動して(とにかく私のターミナルに)出力されThing: { value: 4}、条件が真であったことが示されます。

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