(A == 1 && a == 2 && a == 3) doğru olarak değerlendirilebilir mi?


2484

Moderatör notu: Lütfen kodu düzenleme veya bu bildirimi kaldırma isteğine karşı koy. Beyaz alanın deseni sorunun bir parçası olabilir ve bu nedenle gereksiz yere kurcalanmamalıdır. Eğer "boşluk önemsiz" kampındaysanız, kodu olduğu gibi kabul edebilmelisiniz.

JavaScript ile (a== 1 && a ==2 && a==3)değerlendirmek mümkün mü true?

Bu, büyük bir teknoloji şirketi tarafından sorulan bir röportaj sorusudur. İki hafta önce oldu, ama hala cevabı bulmaya çalışıyorum. Günlük işimizde böyle bir kod yazmadığımızı biliyorum, ama merak ediyorum.


9
Yorumlar uzun tartışmalar için değildir; bu sohbet sohbete taşındı .
deceze

109
Görünüşe göre bunu çok geniş olarak cloae'ye oylayan kişilere : Javascript'teki bir kazı, çok fazla geçerli cevap olduğunu söylüyor mu?
Ocak'ta

24
Bazı insanlar neyin mümkün olduğunu felsefe etmek için etrafta otururlar. Diğerleri, çabalarını müşterileri için uygun, iş için doğru ürünler inşa edip etmediklerine odaklarlar. IMO, bu sorunun hiçbir zaman bir röportajda bu tür soruları sormamanız veya bu tür bir kod yazmamanızın ötesinde pratik bir faydası yoktur. Bu yüzden kapatılmalıdır. Demek istediğim, iş, etrafına oturup bu şeyler hakkında konuşmak için birine gerçek para ödediklerinin farkında mı?
P.Brian.Mackey

15
Cevapları okuduktan sonra, hikayenin ahlakları şunlardır: ==demek istediğinizde kullanmayın ===, ASCII olmayan değişken adlarını yasaklayan bir kodlama standardına sahip olun ve önceki iki ahlakı uygulayan bir linting sürecine sahip olun.
Jesse C. Slicer

87
Moderatör notu: Stack Overflow, söz konusu olana farklı dillerde cevap veren insanların geçmişine sahipti. Bunlar şunlardır onlar farklı bir dilde olsa genel sorununa çözüm çünkü soruyu cevaplamak için girişimleri. Lütfen "yanıt değil" olarak işaretlemekten kaçının. Bunu söyledikten sonra, lütfen farklı dillerde daha fazla yanıt göndermekten de kaçının - bu sorunun diğer bazı cevapların altındaki yorumlarda belirtildiği gibi JavaScript'e özgü bir nedeni vardır ve dile özgü sorularımızı sevmemizin bir nedeni vardır. öyle kalmak için.
BoltClock

Yanıtlar:


3323

Nasıl ==çalıştığından faydalanırsanız, her üç koşulu da karşılayacak şekilde her kullanıldığında geri döndüğünü değiştiren özel toString(veya valueOf) işlevli bir nesne oluşturabilirsiniz .

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

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


Bunun nedeni gevşek eşitlik operatörünün kullanılmasıdır. Gevşek eşitlik kullanılırken, işlenenlerden biri diğerinden farklıysa, motor birini diğerine dönüştürmeye çalışır. Solda bir nesne ve sağda bir sayı valueOfolması durumunda, ilk önce çağrılabilir ise çağırarak nesneyi bir sayıya dönüştürmeye çalışır ve başarısız olursa çağrılır toString. toStringBu durumda kullandım çünkü akla gelen şey valueOfdaha mantıklı olurdu. Bunun yerine bir dize döndürdüğümde toString, motor dizeyi bize biraz daha uzun bir yolla olsa da aynı sonuç veren bir sayıya dönüştürmeye çalışırdı.


70
Zımni valueOf()işlemi değiştirerek bunu başarabilir misiniz ?
Sterling Archer

43
Evet, valueOf aynı nedenden ötürü toString yerine çalışıyor
Kevin B

4
Yorumlar uzun tartışmalar için değildir; bu sohbet sohbete taşındı .
deceze

13
Göre bu sayı dönüşüm böylece ilk denenecek valueOfbiraz daha iyidir.
Salman A

6
@Purferret eşitlik karşılaştırmasının sol tarafındaki bir sayı değil, bir nesnedir. Bu nesnenin üzerinde bir sayı özelliği olması imotoru rahatsız etmez. ;)
18'de 13

2057

Karşı koyamadım - diğer cevaplar şüphesiz doğrudur, ancak gerçekten aşağıdaki kodu geçemezsiniz:

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

İfadedeki garip aralığa ifdikkat edin (sorunuzdan kopyaladığım). ECMA betiği tarafından boşluk karakteri olarak yorumlanmayan bir Unicode boşluk karakteri olan yarım genişlikli Hangul'dur (tanıdık olmayanlar için Korece'dir) - bu, tanımlayıcı için geçerli bir karakter olduğu anlamına gelir. Bu nedenle, biri a'dan sonra Hangul, diğerinden önce ve sonuncusu sadece a ile olmak üzere tamamen farklı üç değişken vardır. Alanı _okunabilirlik ile değiştirmek, aynı kod şöyle görünecektir:

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

Mathias değişken adı doğrulayıcısındaki doğrulamayı kontrol edin . Bu garip boşluk aslında sorularına dahil edilmişse, bu tür bir cevap için bir ipucu olduğundan eminim.

Bunu yapma. Ciddi anlamda.

Düzenleme: Değişken adlarında Sıfır genişlikli mafsal ve Sıfır genişlikli marangoz olmayan karakterlere de izin verildiği dikkatimi çekti - bkz. Sıfır genişlikli karakterlerle JavaScript gizleme - artıları ve eksileri ? .

Bu şu şekilde görünecektir:

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
Orijinal sorudaki garip aralığa bakılırsa, bunun RÖZLE, görüşme sorusunun aradığı cevap - boşluklara benzeyen boşluk olmayan karakterlerden yararlanmak olduğunu düşünüyorum. İyi nokta!
Baracus

18
@Baracus Kevin'in cevabı hakkındaki yorumunda bana bu (korkunç) tekniği hatırlatan garip aralığı fark eden RonJohn'du, bu yüzden onu tespit etmek için kredi alamıyorum. Kimse bu konuda zaten cevap vermişti, bir yerde bir blog yazısı nedeniyle birkaç yıl önce gitti gibi biraz şaşırdım - Ben şimdiye kadar oldukça yaygın bir bilgi olduğunu varsaydım.
Jeff

102
Tabii ki, bu röportajlar için de geçerli olan standart bir boşluk olarak yasaklanmıştır . [alıntı gerekli]
San23'te

13
Orijinal aralık göz önüne alındığında, daha da kötü olabilir, yani bir değişken var ᅠ2 = 3kullanılmıştır; bu yüzden üç değişken vardır aᅠᅠ= 1, ᅠ2 = 3, a = 3( a␣ = 1, ␣2 = 3, a = 3öyle ki (a␣==1 && a==␣2 && a==3))…
Holger

2
@ AL-zami, değişkenlerin ikisinde ekranınızda bir boşluk olarak gösterilen, ancak tanımlayıcının bir parçası olarak yorumlanan, yani üç ayrı değişken vardır - a, a ve a - ekstra karakter vardır. Hangul'un yarı genişlikli alanı.
Jeff

620

BU MÜMKÜN!

var i = 0;

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

Bu, üç farklı değeri değerlendirmek için withdeyimin içinde bir alıcı kullanır a.

... bu hala bunun gerçek kodda kullanılması gerektiği anlamına gelmez ...

Daha da kötüsü, bu hile de kullanımı ile çalışacaktır ===.

  var i = 0;

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


65
Evet aynı şeyi deniyordum :) Röportajdaki doğru cevap, "Bu benim kodumda olamaz çünkü asla kullanmam with."
Sivri

7
@Pointy - Ve, withizin verilmeyen katı modda programlıyorum .
jfriend00

6
Kabul edilen cevap @Pointy onlar olmadan benzer bir şey withgerçekleşmesi böylece
Jungkook

2
@ jorrit kimse kullanmazdı ==. Ve ===kabul edilen cevabı önler
Jonas Wilms

4
@JonasW. Bir çok insan hala kullanıyor ==ama o withzamandan beri görmedim ... aslında JS belgelerinin dışında "lütfen bunu kullanmayın" der. Her neyse, güzel bir çözüm.
wortwart

516

Alıcı veya değer içermeyen örnek:

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

Bu çalışır çünkü hangi dizileri ==çağırır çağırır .toString.join

Bir Symbol.toPrimitiveES6 eşdeğeri olan başka bir çözüm toString/valueOf:

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

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


9
without valueOf, şey ... daha dolaylı ama temelde aynı şey.
Jonas Wilms

11
Bu çözümü gerçekten çok seviyorum çünkü nesnelerin kendi birleştirme işlevinden başka bir şeyi geçersiz kılmıyorsunuz ve mantığı doğru değerlendirmeyi sağlayan çok temiz ve okunması kolay bir kesmek.
Alex Pedersen

28
Dürüst olmak gerekirse, bunun en iyi cevap olduğunu düşünüyorum. Sıra dışı bir şey içermez, sadece birkaç değer belirler. Temel JS bilgisi ile bile anlaşılması çok kolaydır. Aferin.
Zac Delventhal

14
Bu neredeyse faydalı olduğunu hissettiriyor.
Andrew

7
Yanıtların çoğunun kötüye kullanım toStringveyavalueOf ama bu bir bekçi dışında tamamen beni yakaladı. Çok zekice ve ben .joindahili olarak aradığını bilmiyordum , ama tam mantıklı.
GBarroso

268

Mümkün olup olmadığı sorulursa (ZORUNLU değil), "a" dan rastgele bir sayı döndürmesini isteyebilir. Sırasıyla 1, 2 ve 3 üretmesi doğru olur.

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
Diğer çözümleri bilsem bile bu cevabı kasten verirdim, çünkü soruyu cevaplıyor, ancak açıkçası onların peşinde oldukları şey değil. Aptal oyunlar oynayın, aptal ödüller kazanın.
ESR

2
Peki ya 1000'den fazla deneme sürerse?
Piyin

9
@Piyin 1000 denemeden fazla sürerse bir ödül kazanırsınız!
Skeets

5
Bu cevap gibi ben aşırı alarak bu mümkün olduğunu göstermektedir çünkü herhangi bir program çalışırken CPU kayıtları / yeterli kozmik ışınlar ile vurmak olsun önbellek eğer dil, ya da bir kasıtlı başarısızlık dalı arasında böyle bir güç aksaklık gerçekleştirir eğer eğer koşullu aslında sıçramıyor.
Ponkadoodle

En düşük: 1, En yüksek: 412.
KyleFairns

210

Normal ifadeler olmadan hiçbir şey yapamadığınızda:

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

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

valueOfObject, ilkel (Number gibi) ile karşılaştırıldığında çağrılan özel yöntem nedeniyle çalışır . Ana hile, a.valueOfher defasında bayrakla execdüzenli ifadeyi çağırdığı için her seferinde yeni değer döndürür g, bu da lastIndexher eşleşme bulunduğunda düzenli ifadenin güncellenmesine neden olur . İlk kez this.r.lastIndex == 0eşleşir 1ve güncellenir lastIndex:, bir this.r.lastIndex == 1dahaki sefere regex eşleşir 2vb.


22
@Abdillah bir regex nesnesi eşleştiği son dizini hatırlayacak, exectekrar çağırmak o dizinden aramaya başlayacaktır. MDN çok açık değil.
Simon Chan

Görüyorum ki, this.rnormal ifade nesnesi durumu / dizini hatırlıyor. Teşekkürler!
Abdillah

Ben bir dizeyi execolsa, dizgi tam sayı değil geçmek için tavsiye ediyoruz .
Bergi

regex kullanın ve şimdi iki sorun var
Aleksey Solovey

191

Küresel kapsamda aşağıdakiler kullanılarak gerçekleştirilebilir. İçin nodejskullanım globalyerine windowaşağıdaki kodu.

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

Bu yanıt, değişkeni almak için bir alıcı tanımlayarak yürütme bağlamında genel kapsam tarafından sağlanan örtük değişkenleri kötüye kullanır.


Bu varsayıldığı gibi görünmeyen abir özelliktir this. aYerel bir değişken olsaydı (ki buna benziyor), bu işe yaramazdı.
jfriend00

1
@ jfriend00, var a yerleştirirseniz; yere?
jontro

Evet. Referans a == 1daha ima adeğişken bir yerde değil, bir özelliktir this. Genel olarak, her ikisinin de doğru olabileceği küreseller gibi tuhaf bir yer olsa da, genellikle, bir değişkenle var aveya bir kodla varsaydığınız gibi bir özellik olarak erişmenizi sağlayan let ahiçbir thisşey olmadığı anlamına gelir a. Yani, kodunuz görünüşte garip bir küresel değişken şey varsayıyor. Örneğin, kodunuz bir işlev içindeki katı modda çalışmaz ve node.js'de çalışmaz. Kesin çalıştığı koşulları belirtmeli ve muhtemelen neden çalıştığını açıklamalısınız. Aksi takdirde yanıltıcıdır.
jfriend00

@ jfriend00 iyi eminim. Diğer yanıtlarla birlikte çok daha fazla değer katacağından emin değilim. Cevabı güncelleyecek
jontro

14
Soru, bu "hiç" doğru olabilir miydi. Ve cevap evet, ve bu doğru olabileceği senaryolardan biri: ayerel bir değişken değil ve küresel kapsamda artan bir alıcı ile tanımlanıyor.
Zac Delventhal

190

Bu, değişkenin abir SharedArrayBuffer ve bazı ana komut dosyası aracılığıyla erişmesi durumunda mümkündür . Olasılık düşüktür, ancak kod makine koduna derlenmiş zaman, web işçileri değişkeni güncellemek mümkündür asadece şartlarda bu yüzden zamanında a==1, a==2ve a==3koşullar sağlanır.

Bu, web çalışanları ve JavaScript'te SharedArrayBuffer tarafından sağlanan çok iş parçacıklı ortamdaki yarış durumuna bir örnek olabilir.

Yukarıdakilerin temel uygulaması:

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'imde, ilk denemede yaklaşık 10 milyar yinelemeden sonra gerçekleşiyor:

resim açıklamasını buraya girin

İkinci deneme:

resim açıklamasını buraya girin

Dediğim gibi, şansı düşük olacak, ancak yeterli zaman verildiğinde, duruma çarpacak.

İpucu: Sisteminizde çok uzun sürerse. Sadece deneyin a == 1 && a == 2ve değiştirmek Math.random()*3için Math.random()*2. Listeye gittikçe daha fazla eklemek, vurma şansını azaltır.


50
Dürüst olmak gerekirse, bu en iyi cevap. Diğer tüm cevaplar, derinden sezgisel olmayan bir şey yapmak için kasıtlı bir girişim gerektirir. Bu cevap aslında gerçek dünyada olabilecek bir şeyi yansıtıyor - bir yarış durumu.
Tom Swirly

34
Sadece bu da değil - bunun gerçek dünyada olduğunu gördüm. Sorunun tam koşulu ile değil, kesinlikle bir fonksiyonun başlangıcında (a == 1) ve daha sonra fonksiyonun (a == 2) kontrolünde ve kodun her iki koşula da çarpmasıyla. FYI, bunu ilk gördüğümde bir araba motoru kontrolöründeydi ve kodlama standartlarını yerine getirdik. İkinci kez askeri uçaklar için bir saman ve alev dağıtıcı sistemindeydim ve şirketteki ilk günümde bunu buldum ve düzelttim, ekibin geri kalanı hala sorunu tartışıyordu. (Kudos seviyesi: yüksek! :)
Graham

38
Yani, web çalışanları ile javascript programlanmış "araba motor kontrolörleri" ve "saman ve parlama dağıtıcı sistemleri" üzerinde çalıştınız mı? Tekrar dışarı çıkacağımı sanmıyorum.
psaxton

12
@psaxton :) Elbette hayır - ama paylaşılan verilerle çok iş parçacıklı bir yazılımımız var. Bu, Javascript'e veya web çalışanlarına özgü olmayan tüm çok iş parçacıklı yazılımlar için bir anti-desendir. Montaj dili, Brainf * ck, Visual BASIC, C veya Javascript ile programlama yapmanız önemli değildir - bunu çok iş parçacıklı bir uygulamada paylaşılan verilerle yaparsanız , her zaman başarısız olur.
Graham

4
Sanırım bu şimdi @ jontro'nun cevabı etrafında ayrıntılı bir paket.
qntm

148

Bu, bir dizi kendi kendine yazma alıcısı kullanılarak da mümkündür:

(Bu jontro'nun çözümüne benzer, ancak karşı değişken gerektirmez.)

(() => {
    "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
Bir alıcı kullanma yaklaşımının ===sadece değil, aynı zamanda işe yaradığını unutmayın ==.
Makyen

Bu çözüm this, ok işlevinin gövdesi içinde küresel nesne olmaya dayanır .
Roy Tinker

@Midnightas Başka cevapları "piramit kodu" olarak kategorilere ayırmam .
Patrick Roberts

Bunun keyfi düzen ile de çalıştığını unutmayın, değil mi? Gibi (a == 3 && a == 2 && a == 1)?
Johannes

131

Alternatif olarak, bunun için bir sınıf ve çek için bir örnek kullanabilirsiniz.

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

var a = new A;

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

DÜZENLE

ES6 sınıflarını kullanmak şöyle görünecektir

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
sadece function A() {value = 0;başlangıçta mı?
Dave C

valueOfgeçersiz this method is usually called automatically by JavaScript behind the scenes, and not explicitly in code
kılınıyor

130

Bu cevabın daha önce gönderildiğini görmüyorum, bu yüzden bunu da karışıma atacağım. Bu Jeff'in yarı genişlikte Hangul alanıyla verdiği cevaba benzer .

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

İkincisi ile hafif bir tutarsızlık fark edebilirsiniz, ancak birinci ve üçüncü çıplak gözle aynıdır. Her üçü de ayrı karakterdir:

a- Latin küçük harf A
- Tam Genişlik Latin küçük harf A
а- Kiril küçük harf A

Bunun genel terimi "homoglifler" dir: aynı görünen farklı unicode karakterler. Tipik olarak tamamen ayırt edilemeyen üç tane elde etmek zordur , ancak bazı durumlarda şanslı olabilirsiniz. A, Α, А ve Ꭺ daha iyi çalışacak (Latince-A, Yunan Alpha , Kiril-A ve Cherokee-A ; sırasıyla maalesef Rum ve Cherokee küçük harfler Latin çok farklıdır a: α, ve doesn böylece yukarıdaki pasajda yardım etmeyin).

Orada, genellikle sahte etki alanı adlarında (örneğin, wikipediа.org(Kiril) ve wikipedia.org(Latin)) bir Homoglif Saldırısı sınıfı var , ancak kodda da görünebilir; tipik olarak el değmemiş olarak adlandırılır (bir yorumda belirtildiği gibi, [el değmemiş ] sorular artık PPCG'de konu dışıdır , ancak bu tür şeylerin ortaya çıkacağı bir tür zorluk olarak kullanılır). Kullandığım bu web sitesini Bu yanıt için kullanılan homoglyphs bulmak için.



4
@hvd Tamamen yazı tipi oluşturma işleminize bağlıdır. Gördüğüm bu .
Draco18s artık SE

1
@Jake Evet, Tam Genişlik Latin küçük A harfi en büyük homoglif değildir (ancak büyük harf varyantları şaşırtıcıdır). Genellikle istenen etkiyi elde etmek için sadece iki taneye ihtiyacınız vardır.
Draco18s artık SE

@ Draco18s Kabul etti: sadece 2 genellikle gerekli. Ekstra bilgi de iyi iş!
JakeSteam

10
Ayrıca unicode varyant seçiciyi de kullanabilirsiniz (U + FE00..U + FE0F). Bunların hiçbiri şunlardır a: a︀ a︁ a︂. Artık tutarsızlıklar konusunda endişelenmenize gerek yok.
Salman A

108

Evet mümkün! 😎

»JavaScript

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

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

Yukarıdaki kod kısa bir sürümdür (yorumlardaki notu için @Forivin sayesinde) ve aşağıdaki kod orijinaldir:

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;}

Kodumun üst tarafını görüp çalıştırırsanız WOW diyorsunuz, nasıl?

Sanırım Evet demenin yeterli olduğunu size söyleyen biri için mümkün : Hiçbir şey imkansız değil

Hile: ifİsminin benzer olduğu bir işlevi yapmak için daha sonra gizli bir karakter kullandım if. JavaScript'te anahtar kelimeleri geçersiz kılamıyoruz, bu yüzden bu şekilde kullanmak zorunda kaldım. Bu sahte if, ama bu durumda sizin için çalışıyor!


» C #

Ayrıca ( özellik değeri artış tekniği ile ) bir C # sürümü yazdım :

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!😎");
    }
}

Canlı Demo


56
Javascript versiyonu insanlığa karşı gerçek bir suçtur ve bunu yapabilme yeteneği BM sözleşmeleri tarafından yasadışı olmalıdır. Bence dünyayı tüm javacript bilgisinden arınmanın zamanı geldi.
Daha

2
İşlev bildirimi daha da kısa olabilir. if‌=()=>!0
Forivin

4
Neden dünyada kullandın document.write? Cevabın geri kalanından bağımsız olarak işe alınmamak için kesin bir yol.
Cerbrus

3
@ Cerer, notun için teşekkürler. Önce cevabımı yazdım console.logama document.write olarak değiştirdim. Gerçekten her zaman console.logkodlarımda kullanıyorum ama burada sadece StackOverflow kod snippet kutusundaki kullanıcılara bir metin göstermek istiyorum. Bu yüzden mesajımı, oluşturduğu mesajdan daha güzel göstermek istedim console.log. Run Code SnippetCevabımdaki ve diğer yanıtlardaki düğmeyi tıklayın . SO Kod Parçacığı html ve JS ve CSS kullanmama izin verin, sonra cevabımda kullanmak ve güzel yapmak istedim. Bence herhangi bir olumsuz yan etkisi yoktur ve cevabımı büyük veya karmaşık yapmamıştı.
RAM

1
@Clearer, BM Sözleşmeleri dünyayı etkili bir şekilde değiştirebilseydi, bundan daha iyi bir dünyaya sahip olmalıyız. BM'deki ifadeden daha fazlasına ihtiyacımız var ve o güne kadar bu Javascript hilemi kullanabiliriz;)
RAM

97

JavaScript

a == a +1

JavaScript'te, çift ​​duyarlıklı kayan nokta sayısı olarak uygulanan tamsayılar değil, yalnızca s'ler vardır Number.

Bir Sayı ayeterince büyükse, art arda üç tamsayıya eşit sayılabileceği anlamına gelir :

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

Doğru, görüşmecinin tam olarak sorduğu şey değildir (çalışmaz a=0), ancak gizli işlevler veya operatör aşırı yüklemesi ile herhangi bir hile içermez.

Diğer diller

Referans olarak, a==1 && a==2 && a==3Ruby ve Python'da çözümler var . Küçük bir değişiklikle Java'da da mümkündür.

Yakut

Bir özel ile ==:

class A
  def ==(o)
    true
  end
end

a = A.new

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

Veya artan a:

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

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

piton

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

Java Integerönbelleğini değiştirmek mümkündür :

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 :) Zaten yeterince iyi JS cevabı var. Sadece diğer dillerde nasıl yapılabileceğini göstermenin ilginç olacağını düşündüm ve muhtemelen JS geliştiricilerine bazı fikirler verdim.
Eric Duminil

2
@ cᴏʟᴅsᴘᴇᴇᴅ: Bir JS örneği ile güncellendi.
Eric Duminil

1
Java sürümü neden çalışmıyor Integer a = 42(veya çalışıyor)? Ben otomatik boks anladığım gibi, Integer a = 42; a == 1 && a == 2 && a == 3tüm ints kutu gerekir. Yoksa karşılaştırmalar için bu kutunun a kutbu mu?
CAD97

@ CAD97: Integer == intkutudan çıkarmayla sonuçlanıyor gibi görünüyor. Ama Integer#equals(int)otomatik boksu zorlar, bu yüzden çalışır. Yorum için teşekkürler!
Eric Duminil

@StephanBijzitter: Lütfen açıklayınız. Bildiğim kadarıyla, sadece NumbersJS, temelde doubles gibi vardır . Tamsayılara benzeyebilirler ve tamsayılar gibi kullanabilirsiniz, ancak yine de tamsayı değildir. n == n + 1Java / Python / C / Ruby / ... tamsayıları için hiç doğru olamaz sanmıyorum
Eric Duminil

80

Bu bir ters versiyonudur Jeff'in cevabı @ gizli karakteri (U + 115F, U + 1160 veya U + 3164) gibi o bakış değişkenleri oluşturmak için kullanılır * 1, 2ve 3.

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

* Bu cevap sıfır genişlikli mafsalsız (U + 200C) ve sıfır genişlikli mafsal (U + 200D) kullanılarak basitleştirilebilir. Bu karakterlerin her ikisine de tanımlayıcıların içinde izin verilir, ancak başlangıçta izin verilmez:

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);
****/

Diğer hileler aynı fikri kullanarak mümkündür, örneğin tam olarak ( a︀ = 1; a︁ = 2; a︀ == 1 && a︁ == 2; // true) benzer görünen değişkenler oluşturmak için Unicode varyasyon seçicileri kullanarak .


75

Mülakatların birinci kuralı; asla imkansız demeyin.

Gizli karakter numarasına gerek yok.

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
Ahh. __defineGetter__aslında js dilinin bir parçası değil, sadece çirkin bir versiyonudur defineProperty. typeofbir işlev değildir ve bu bildirilmemiş iolan sadece korkunçtur. Hala 40 puan değerinde gibi görünüyor: /
Jonas Wilms

6
@JonasW. 41 upvotes :-) Bunun developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… 'a göre__defineGetter__ kullanımdan kaldırıldığının farkındayım, ancak FireFox v 57.0.4'te açıkça yürütüldüğünden bunu göstermeyi tercih ettim çünkü eski kod gerçek ve göz ardı edilemez. Çirkinliğe bakılmaksızın, yaptığım şekilde ilan etmek iyi bilinen / belgelenen bir davranış. Belki de sadece PCG havasındaydım ¯ \ _ (ツ) _ / ¯defineProperty()i
MonkeyZeus

68

Dürüst olmak gerekirse, doğru olup olmadığını değerlendirmenin bir yolu olup olmadığı (ve diğerlerinin de gösterdiği gibi, birçok yol var), yüzlerce röportaj yapan biri olarak konuşurken, aradığım cevap boyunca bir şey:

"Eh, belki evet hemen benim için açık olmayan bazı garip koşullar altında ... ama bunu gerçek kodla karşılaşırsam o zaman ne yaptığını ve neden yaptığını anlamak için ortak hata ayıklama tekniklerini kullanırdım ve sonra hemen bu durumu önlemek için kodu yeniden düzenleyin ... ama daha da önemlisi: Ben kesinlikle ASLA bu kodu ilk etapta yazmak istiyorum çünkü bu kıvrımlı kod tanımı ve asla kıvrımlı kod yazmak için çalışıyoruz ".

Sanırım bazı görüşmeciler, çok zor bir soru olması gerektiği anlamına gelmekle suçlanırlar, ancak bir fikri olan geliştiricilere, özellikle de akılcı düşünceyle destekleyebilecekleri ve sorumu kendileri hakkında anlamlı bir ifade.


13
Soru (ya da tüm mülakat soruları) muhtemelen bir sorun hakkında düşünmeye istekli olan adayları, özellikle de bunun gibi "açık bir şekilde açık" olanları test etmektir. Yanıtı "bildiğine" inandıkları için düşünmeyi reddeden biri iyi bir işe alım değildir.
Shammoo

5
@Don Hatch Hayır, iyi niyetle cevap verirlerse ve özellikle diğerlerinin gösterdiği gibi doğru bir cevap verdiyse onları cezalandırmazdım ... ama daha sonra bunun bir düşünüp düşünmediklerini araştırmak için bir takip isteyeceğim. kod yazmanın iyi bir yolu. Bilgili olmak ve "doğru" bir cevap bulmak, iyi bir geliştirici olmanın sadece bir parçasıdır. "Profesyonel" bir geliştirici için çok daha önemli olan, çoğu zaman daha az yetenekli geliştiriciler tarafından anlaşılabilir ve bakımı kolay bir kod yazmaktır. Aşırı zeki geliştiriciler, imkansız olanlar IME kadar kötü.
Frank W. Zammetti

16
Bu soruya cevap vermiyor.
TylerH

6
Bu cevabın üzücü yanı, 1rep kullanıcısının dün bunu yanıtlaması ve bu soruyu silmesine neden olan 2 downvotes almasıdır.
Jonas Wilms

8
@JohnColeman sorusu, kodun nasıl doğru olarak değerlendirilebileceğini sorar. Görüşmecinin soruyu en başta önermesinin nedenlerini sormaz. Bu cevap, sorulan soruyu ele almaya bile çalışmaz ve bunun yerine tamamen görüşmecinin amacının ne olduğunu tahmin etme girişiminin "ne yapacağım" versiyonuna odaklanır. Sorulan soru bu olsaydı, çok geniş olurdu. Bu nedenle bu cevap buraya veya sitenin herhangi bir yerine ait değildir.
TylerH

43

Böyle bir röportaj sorusu alırsanız (veya kodunuzda eşit derecede beklenmedik bir davranış fark ederseniz) ilk bakışta imkansız görünen bir davranışa ne tür şeylerin neden olabileceğini düşünün:

  1. Kodlama : Bu durumda, baktığınız değişken düşündüğünüz değişken değildir. Bu, değişkenin adını başka bir değişkene benzetmek için homoglifler veya boşluk karakterleri kullanarak kasıtlı olarak Unicode ile uğraşırsanız , ancak kodlama sorunları yanlışlıkla, örneğin beklenmedik Unicode kodu içeren Web'den kod kopyalayıp yapıştırırken de ortaya çıkabilir. (örneğin, bir içerik yönetim sistemi flUnicode 'LATIN SMALL LIGATURE FL' (U + FB02) ile değiştirmek gibi bazı "otomatik biçimlendirme" yaptığı için ).

  2. Yarış koşulları : Bir yarış koşulu meydana gelebilir, yani kodun geliştirici tarafından beklenen sırada yürütülmediği bir durum. Yarış koşulları genellikle çok iş parçacıklı kodda gerçekleşir, ancak yarış koşullarının mümkün olması için birden fazla iş parçacığı şart değildir - eşzamansızlık yeterlidir (ve kafanız karışmaz, eşzamansız kaputun altında birden fazla iş parçacığının kullanıldığı anlamına gelmez ).

    Bu nedenle, JavaScript'in tek iş parçacıklı olduğu için yarış koşullarından da bağımsız olmadığını unutmayın. Basit tek iş parçacıklı - ancak zaman uyumsuz - örnek için buraya bakın . Tek bir açıklama bağlamında, yarış koşulunun JavaScript'te vurulması oldukça zor olacaktır.

    Birden fazla iş parçacığına sahip olabileceğiniz için web çalışanlarıyla JavaScript biraz farklıdır. @mehulmpt bize web çalışanlarını kullanan harika bir kavram kanıtı gösterdi .

  3. Yan etkiler : Eşitlik karşılaştırma işleminin bir yan etkisi (buradaki örneklerde olduğu gibi açık olması gerekmez, genellikle yan etkiler çok incedir).

Bu tür sorunlar yalnızca JavaScript değil, birçok programlama dilinde de görünebilir, bu yüzden burada klasik JavaScript WTF'lerinden birini görmüyoruz 1 .

Tabii ki, görüşme sorusu ve buradaki örneklerin hepsi çok tutarlı görünüyor. Ancak bunlar iyi bir hatırlatmadır:

  • Yan etkiler gerçekten kötü olabilir ve iyi tasarlanmış bir programın istenmeyen yan etkilerden arınmış olması gerekir.
  • Çok iş parçacıklı ve değişken durum sorunlu olabilir.
  • Karakter kodlama ve dize işleme hakkı yapmamak kötü hatalara yol açabilir.

1 Örneğin, burada bir yan etki (belirgin bir) gösteren tamamen farklı bir programlama dilinde (C #) bir örnek bulabilirsiniz .


1
Sonra, soru çok geniş hale geliyor. Farklı diller bunu farklı derecelerde kolaylıkla uygulayabilir. Soru, JS'ye özel bir Soru-Cevap olduğu için çok fazla çekiş kazandı, ancak bu sadece benim 2c.
cs95

1
nedenleri farklı C # ve javascript olduğundan bu cevap yasal değildir.
Edwin

3
@Edwin: Sebepleri tamamen aynı: Benzer görünümlü glifler veya boşluk karakterleri, yarış koşulları veya karşılaştırma işleminin (ikincisinde örneğimde gösterilen) yan etkileri ile Unicode uğraşmak.
Dirk Vollmar

2
@ cᴏʟᴅsᴘᴇᴇᴅ: Bazen olaylara daha geniş bir açıdan bakmak asıl sorunun görülmesine yardımcı olur.
Dirk Vollmar

3
Keşke bu cevap bu soruya "meta" bir şekilde etiketlenebilseydi. JS varmış gibi üstündeki tüm cevapları okuduktan sonra, bu duyguyu bırakıldı yüzden birçok delik, ama sadece tek bir seferde tüm cevapları özetlenebilir. Ve bunu, bence bunu yıldız görüşmesi sorusuna (dile özgü etiket kaldırılmışsa) dönüştürecek şekilde yaptınız. Bravo!
KCE

41

İstediğiniz değerleri çıkarmak için bir dizi kullanan başka bir varyasyon.

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

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


31

Tamam, jeneratörlerle başka bir hack:

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!');
}


Hack diyorsunuz, ama eminim ki bu jeneratörlerin kullanım durumu ... :) ( thisbunun pencere nesnesi olmasına dayanması dışında )
Cody G

29

Proxy Kullanımı :

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

Proxy'ler temel olarak bir hedef nesne (ilk parametre) gibi davranır, ancak hedef nesne üzerinde (bu durumda "get property" işlemi) kesişme işlemleri yapar, böylece varsayılan nesne davranışı dışında bir şey yapma fırsatı olur. Bu durumda, türünü her sayı ile karşılaştırmak için zorladığı azaman "özellik al" eylemi çağrılır ==. Bu olur:

  1. Mülkün sayacımız { i: 0 }olduğu bir hedef nesne oluşturuyoruzi
  2. Hedef nesne için bir Proxy oluşturup a
  3. Her a ==karşılaştırma için, atürü ilkel bir değere zorlanır
  4. Bu tip baskılar a[Symbol.toPrimitive]()dahili olarak arama ile sonuçlanır
  5. Proxy a[Symbol.toPrimitive], "get handler" kullanarak işlevi almayı durdurur
  6. Mülkiyet kazanılmış olan o vekilin "işleyicisi olsun" kontrol eder Symbol.toPrimitive, bu durumda o artırır ve daha sonra hedef nesneden sayacı döndürür: ++target.i. Farklı bir özellik alınıyorsa, varsayılan özellik değerini döndürmeye geri döneriz,target[name]

Yani:

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

Diğer cevapların çoğunda olduğu gibi, bu sadece gevşek bir eşitlik kontrolü ( ==) ile çalışır , çünkü katı eşitlik kontrolleri ( ===) Proxy'nin araya girebileceği tipte baskı yapmaz.


2
Bununla birlikte, bunun için bir proxy kullanmanın bir anlamı yoktur - Symbol.toPrimitivebir nesne üzerinde aynı şekilde tanımlamak da aynı şekilde işe yarayacaktır.
Ry-

27

Aslında sorunun ilk kısmına verilen cevap her programlama dilinde "Evet" dir. Örneğin, bu C / C ++ durumunda:

#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
Her programlama dilinde mümkün olduğunu düşünmüyorum . Örneğin her dilde önişlemci yoktur. Bu nedenle, tüm diller &&mantıksal "ve" için kullanılmaz.
Keith Thompson

3
Ben hem çalışan bir yolunu bulmuş Python ve C ++ operatör aşırı yüklenmesini kullanır.
Donald Duck

7
Ya da yansıma kullanarak ve tamsayı önbelleğini karıştırarak Java'da yapabilirsiniz.
CAD97

7
Bu noktada mutasyonu desteklemeyen dillerde yapamıyorum, örneğin haskell'de karşılaştırılabilir hiçbir şey yok
Jason Carr

4
Soru C ++ değil, JavaScript hakkında soruyor.
Tüm İşçiler

26

Aynı, ancak farklı, ama yine de aynı (birden çok kez "test edilebilir"):

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!');
}

Fikrim Number nesne türü denkleminin nasıl çalıştığıyla başladı.


4
İkinci kez de çalışıyor!
Salman A

25

Sembolleri kullanan bir ECMAScript 6 cevabı:

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

Nedeniyle ==kullanımı, JavaScript zorlamak gerekiyordu aikinci işlenen bir şey yakın içine ( 1, 2, 3bu durumda). Ancak JavaScript kendi başına zorlamayı anlamaya çalışmadan önce aramaya çalışır Symbol.toPrimitive. Symbol.toPrimitiveJavaScript sağlarsanız , işlevinizin döndürdüğü değeri kullanır. Değilse, JavaScript arayacaktır valueOf.


24

Bu uygulamak için en az kod olduğunu düşünüyorum:

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

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

Her çağrıda valueOfgenel bir değişkeni artıran bir özel ile kukla bir nesne oluşturma i. 23 karakter!


14

Bu, global değişkene neden olan hoş bir yan etkiye sahip defineProperty'yi kullanır!

var _a = 1

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

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


8
üzerinde bir kapanış kullanabilirsiniz a: get: (a => () => ++a)(0),küresel gerekmez.
Nina Scholz

13
@NinaScholz elbette, ama burada kötü uygulamalar hakkında konuşuyoruz - sadece şunu yapmama izin ver: D
Ben Aubin

1

valueOfBir sınıf bildiriminde geçersiz kılınarak yapılabilir:

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

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

const a = new Thing();

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

Olan şey, valueOfher karşılaştırma operatörünün çağrılmasıdır. Birincisinde aeşit olacak 1, ikincisinde aeşit olacak 2vb. Çünkü her zaman valueOfçağrıldığında,a artırılır.

Bu nedenle console.log Thing: { value: 4}, koşulun doğru olduğunu belirterek (yine de terminalimde) ateş ve çıkış yapar .

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.