web-gelistirme-sc.com

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

Moderatör notu: Lütfen kodu düzenleme veya bu bildirimi kaldırma dürtüsüne diren. Boşluk düzeni sorunun bir parçası olabilir ve bu nedenle gereksiz yere değiştirilmemelidir. "Boşluk önemsiz" kampındaysanız, kodu olduğu gibi kabul edebilmelisiniz.

(a== 1 && a ==2 && a==3)'un JavaScript'teki true olarak değerlendirilebilmesi mümkün mü?

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

2331

Eğer == nasıl çalışır 'dan faydalanırsanız, her üç koşulu yerine getirecek şekilde kullanıldığında ne döndürdüğünü değiştiren özel bir toString (veya valueOf) işlevine sahip 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 çalışmasının nedeni, serbest eşitlik operatörünün kullanılmasıdır. Gevşek eşitlik kullanıldığında, işlenenlerden biri diğerinden farklı bir türdeyse, motor birini diğerine dönüştürmeye çalışır. Soldaki bir nesne ve sağdaki bir sayı olması durumunda, eğer çağrılabilir ise ilk önce valueOf öğesini çağırarak nesneyi bir sayıya dönüştürmeye çalışacak ve bunu başaramazsa toString öğesini çağıracaktır. Bu durumda toString kullandım, çünkü aklıma ne geldi, valueOf daha anlamlı olurdu. Bunun yerine, toString öğesinden bir dize döndürürsem, motor daha sonra biraz daha uzun bir yol olsa da, dizgiyi bize aynı son sonucu veren bir sayıya dönüştürmeye çalışırdı.

3185
Kevin B

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

if cümlesindeki (sorunuzdan kopyaladığım) garip boşluğu not alın. ECMA betiği tarafından bir boşluk karakteri olarak yorumlanmayan bir Unicode boşluk karakteri olan yarı genişlikte Hangul'dur (tanıdık olmayanlar için Korece olan) - bu, tanımlayıcı için geçerli bir karakter olduğu anlamına gelir. Bu nedenle, biri a'dan sonra Hangul'lu, biri daha önce diğeri sadece a olan üç farklı değişken vardır. Boşluk okunabilirlik için _ ile değiştirilirse, aynı kod şöyle görünür:

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

Çıkış Mathias'in değişken ismi doğrulayıcısındaki doğrulama . Bu garip boşluk aslında sorularına dahil edildiyse, bu tür bir cevap için bir ipucu olduğundan eminim.

Bunu yapma Ciddi anlamda.

Düzenleme: Değişkende (bir değişken başlatmamaya rağmen) Sıfır genişlikli marangoz ve Sıfır genişlikli marangoz olmayan karakterlere de izin verildiğini fark ettim. adları - bkz Sıfır genişlikli karakterlerle JavaScript'i şaşırtmak - artılar ve eksiler? .

Bu, aşağıdakine benzer:

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!")
}
2025
Jeff

BT IS OLASI!

var i = 0;

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

Bu, with öğesinin üç farklı değer olarak değerlendirmesini sağlamak için a ifadesinin içindeki bir alıcı kullanır.

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

Daha da kötüsü, bu numara, === kullanımıyla da çalışacaktır.

  var i = 0;

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

591
Jonas Wilms

Alıcılar veya valueOf olmadan örnek:

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

Bu çalışır çünkü ==, Diziler için .join adında toString öğesini çağırır.

Symbol.toPrimitive 'nin ES6 eşdeğeri olan toString/valueOf kullanarak bir başka çözüm: 

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

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

458
georg

Mümkün olup olmadığı sorulursa (ZORUNLU değil), rastgele bir sayı döndürmek için "a" isteyebilir. Sırayla 1, 2 ve 3 üretirse 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;
    }
  }
}

259
mmmaaa

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

Object ilkel ile karşılaştırıldığında (Number gibi) çağrıldığında custom valueOf yöntemi nedeniyle çalışır. İşin püf noktası, a.valueOf 'nun her seferinde yeni bir değer vermesidir, çünkü exec bayrağı ile düzenli ifadede g' ı çağırır, bu da her zaman eşleşmenin bulunduğu normal ifadenin lastIndex 'nın güncellenmesine neden olur. Yani ilk kez this.r.lastIndex == 0, 1 ile eşleşir ve lastIndex: this.r.lastIndex == 1 'i günceller, böylece bir dahaki sefere regex 2 ve benzerleriyle eşleşir.

203
Kos

Global kapsamda aşağıdakiler kullanılarak gerçekleştirilebilir. nodejs için, aşağıdaki kodda global yerine window kullanın.

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

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

186
jontro

Bu değişken a tarafından erişilebilir olması durumunda mümkündür, örneğin 2 web çalışanı bir SharedArrayBuffer ve bazı ana komut dosyaları yoluyla. Olasılık düşüktür, ancak kod makine koduna derlendiğinde, web çalışanları a değişkenini tam zamanında güncellerler, böylece a==1, a==2 ve a==3 koşulları yerine getirilir.

Bu, web çalışanları ve JavaScript'teki SharedArrayBuffer tarafından sağlanan çok iş parçacıklı ortamda yarış koşulunun bir örneği olabilir.

İşte 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’de ilk denemede yaklaşık 10 milyar yinelemeden sonra gerçekleşiyor:

 enter image description here

İkinci deneme:

 enter image description here

Dediğim gibi, şansın düşük olacak, ama yeterince zaman verildiğinde, şartlara varacak.

İpucu: Sisteminizde çok uzun sürerse. Yalnızca a == 1 && a == 2 dosyasını deneyin ve Math.random()*3 öğesini Math.random()*2 olarak değiştirin. Listeye gittikçe daha fazla ekleme isabet şansını düşürür.

182
mehulmpt

Bu, bir dizi kendi kendine yazılan alıcı kullanarak da mümkündür:

(Bu jontro'nun çözümüne benzer, ancak bir sayaç değişkeni 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.");
    }
})();

145
Patrick Dark

Bu cevabın zaten yayınlanmış olduğunu görmüyorum, bu yüzden bunu da karışıma atacağım. Bu, yarım genişlikte Hangul alanıyla Jeff'in yanıtı öğesine benzer.

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

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

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

Bunun için genel terim "homoglif" dir: aynı görünen farklı unicode karakterler. Tamamen ayırt edilemeyen üç elde etmek genellikle zordur, ancak bazı durumlarda şanslı olabilirsiniz. A, А, А ve better daha iyi sonuç verirdi (Latin-A, Yunan Hareketi , Kiril-A ve sırasıyla Cherokee-A ; ve Cherokee'nin küçük harfleri Latin a'dan çok farklıdır: α, ve bu yüzden yukarıdaki kod parçasına yardımcı olmaz).

Orada en yaygın olarak sahte alan adlarında (örn. wikipediа.org (Kiril) vs wikipedia.org (Latince)) bir Homoglif Saldırısı sınıfı vardır, ancak kodda da gösterilebilir; tipik olarak yetersiz olarak adlandırılır (bir yorumda belirtildiği gibi, [underhanded] soruları şimdi PPCG 'de konu dışıdır, ancak bu türden bir meydan okuma olarak kullanılır şeylerin ortaya çıkması). Bu cevap için kullanılan homoglifleri bulmak için bu web sitesi kullandım.

127
Draco18s

Alternatif olarak, bunun için bir sınıf ve kontrol 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&UUML;ZENLE

ES6 sınıflarını kullanarak bu gibi görünüyor

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

123
Nina Scholz

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 versiyondur (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 sadece üst tarafını görür ve çalıştırırsanız WOW diyorsunuz, nasıl?

Bu yüzden şunu söylemenin yeterli olduğunu düşünüyorum Evet, size söyleyen birine mümkün mümkündür: Hiçbir şey imkansız değildir

Püf noktası: if öğesinden sonra adının if ile aynı olduğunu gösteren bir işlev yapmak için gizli bir karakter kullandım. JavaScript’te, anahtar kelimeleri geçersiz kılmayacağımız için, bu şekilde kullanmak zorunda kaldım. Sahte if, ama bu durumda senin için çalışıyor!


" C #

Ayrıca C # versiyonunu yazdım ( artırma özellik değeri tekniğini ):

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

101
RAM

JavaScript

a == a +1

JavaScript'te, tamsayıları değil, yalnızca çift duyarlıklı kayan nokta sayıları olarak uygulanan Numbers var.

Bir Number a, yeterince büyükse, ardışık üç tam sayıya eşit olarak kabul edilebileceği anlamına gelir:

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

Doğru, görüşmeci tam olarak sorduğu şey değil (a=0 ile çalışmıyor), ancak gizli işlevler veya operatörün aşırı yüklenmesi ile ilgili herhangi bir numara içermiyor.

Diğer diller

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

Yakut

Özel bir == 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.");
        }
    }
}
93
Eric Duminil

Bu, @ Jeff'in cevabının * ters bir versiyonudur, burada gizli bir karakter (U + 115F, U + 1160 veya U + 3164) 1, 2 ve 3 gibi görünen değişkenler oluşturmak için kullanılır.

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

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

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

Aynı fikir kullanılarak ör. Tam olarak birbirine benzeyen değişkenler oluşturmak için Unicode varyasyon seçicileri kullanarak (a︀ = 1; a︁ = 2; a︀ == 1 && a︁ == 2; // true).

78
Salman A

Görüşmelerden biri olan kural; asla imkansız deme.

Gizli karakter kandırması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?' );
}

72
MonkeyZeus

Dürüst olmak gerekirse, bunun doğru olup olmadığını değerlendirmenin bir yolu olup olmadığı (ve diğerlerinin de gösterdiği gibi, çok sayıda yol vardır), aradığım cevap, yüzlerce görüşme yapmış biri olarak konuşma olacaktır. çizgileri boyunca bir şey:

“Evet, belki evet, benim için hemen belli olmayan bazı garip koşullar altında ... ama bunu gerçek kodla karşılaştıysam, ne yaptığını ve neden yaptığını anlamak için ortak hata ayıklama tekniklerini kullanırdım. ve sonra derhal bu durumu önlemek için kodu tekrar gözden geçirin ... ama daha da önemlisi: bu kodu ilk etapta kesinlikle ASLA yazmam çünkü bu, iç içe geçmiş kodun tanımıdır ve asla içindekiler kodunu yazmaya çalışmıyorum ".

Sanırım bazı görüşmecilerin çok zor bir soru olarak adlandırılan şeyin açıkça anlaşılmasının zorlandığını düşünüyorum, ancak özellikle mantıklı bir düşünceyle destekleyebilecekleri ve sorumu çözebilecekleri zaman, bir fikri olan geliştiricilere aldırış etmiyorum. kendileri hakkında anlamlı bir ifade.

66

İşte başka bir varyasyon, istediğiniz değerleri almak için bir dizi kullanarak.

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

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

41
Théophile

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

  1. Encoding: Bu durumda baktığınız değişken, düşündüğünüz gibi değildir. Bu, bir değişkenin adını bir başkasına benzemek için homoglyphs veya boşluk karakterleri kullanarak kasıtlı olarak Unicode ile uğraşırsanız olabilir, ancak kodlama sorunları da yanlışlıkla tanıtılabilir; Beklenmeyen Unicode kod noktaları içeren Web'den kod kopyalayıp yapıştırırken (örneğin, bir içerik yönetim sistemi fl yerine Unicode 'LATIN SMALL LIGATURE FL' (U + FB02) ile değiştirilir gibi bazı "otomatik biçimlendirme" yaptı.

  2. Yarış koşulları: Bir yarış koşulu oluşabilir, yani geliştiricinin beklediği sırada kod çalıştırılmayan bir durum. Yarış koşulları genellikle çok iş parçacıklı kodda meydana gelir, ancak çoklu yarışlar, yarış koşullarının mümkün olması için bir zorunluluk değildir - zaman uyumsuzluğu yeterlidir (ve kafanız karışmaz, zaman uyumsuzluğu başlık altında birden fazla iş parçacığı kullanıldığı anlamına gelmez ). 

    Bu nedenle, JavaScript'in yalnızca tek iş parçacıklı olduğu için yarış koşullarından arındırılmadığını unutmayın. Basit bir iş parçacığı - ancak eşzamansız - örnek için burada bölümüne bakın. Tek bir ifade bağlamında, yarış koşulu ancak JavaScript'te oldukça zor olacaktır.

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

  3. Yan etkiler: Eşitlik karşılaştırma işleminin bir yan etkisi (buradaki örneklerde olduğu kadar açık olması gerekmeyen, çoğu zaman yan etkiler çok belirsizdir). 

Bu tür sorunlar birçok programlama dilinde görünebilir, yalnızca JavaScript'te değil, klasik JavaScript WTF'ler burada da görmüyoruz.1

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

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

1 Örneğin, bir yan etki sergileyen tamamen belirgin bir programlama dilinde (C #) bir örnek bulabilirsiniz (bariz bir tane) burada .

37
Dirk Vollmar

Tamam, jeneratörler ile başka bir kesmek:

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

31
BaggersIO

Aslında, sorunun ilk kısmına 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

Proxy'leri Kullanmak :

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 üzerindeki işlemleri durdurur (bu durumda "özellik al" işlemi), böylece varsayılan nesne davranışından başka bir şey yapma fırsatı vardır. Bu durumda, "get property" eylemi, == türünü her sayı ile karşılaştırmak için zorladığında a üzerinde çağrılır. Bu olur:

  1. { i: 0 } 'da bir hedef nesnesi oluşturuyoruz, burada i özelliği bizim sayacımızdır
  2. Hedef nesne için bir Proxy oluşturup onu a dizinine atarız.
  3. Her a == karşılaştırması için, a 'ın türü ilkel bir değere zorlanır
  4. Bu tür baskı, dahili olarak a[Symbol.toPrimitive]() işlevinin çağrılmasıyla sonuçlanır.
  5. Proxy, "get handler" komutunu kullanarak a[Symbol.toPrimitive] işlevini almayı engelliyor.
  6. Proxy'nin "get işleyicisi", edinilen özelliğin Symbol.toPrimitive olduğunu kontrol eder, bu durumda sayacı artırır ve sonra sayacı hedef nesneden 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 yalnızca gevşek bir eşitlik kontrolü (==) ile çalışır, çünkü katı eşitlik kontrolleri (===), Proxy'nin araya girebileceği bir zorlama türü yapmaz.

27
IceCreamYou

Aynı, ancak farklı, ancak 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!');
}

Benim fikrim Number nesne tipi denkleminin nasıl çalıştığıyla başladı.

26
Preda7or

Sembollerden faydalanan bir ECMAScript 6 cevabı:

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

== kullanımı nedeniyle, JavaScript'in a öğesini ikinci işleyiciye yakın bir şeye zorlaması beklenir (bu durumda 1, 2, 3). Ancak JavaScript kendi başına zorlamayı bulmaya çalışmadan önce, Symbol.toPrimitive öğesini çağırmaya çalışır. Symbol.toPrimitive işlevini verirseniz, JavaScript işlevinizin döndürdüğü değeri kullanır. Değilse, JavaScript valueOf öğesini çağırır.

23
Omar Alshaker

Bunu 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 valueOf bir genel değişkeni artıran özel bir i ile yapay bir nesne oluşturma. 23 karakter!

23
Gaafar

Bu, global değişkene neden olan Nice yan etkisi ile defineProperty ürününü kullanır!

var _a = 1

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

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

11
Ben Aubin

Bir sınıf bildirgesinde valueOf değerini geçersiz kılarak, 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, her karşılaştırma operatöründe valueOf olarak adlandırılıyor. Birincisinde, a, 1 değerine eşit olacak, ikincisi, a, 2 değerine eşit olacak ve böylece devam edecek, çünkü her seferinde valueOf çağrıldığında, a değeri artırılır.

Bu nedenle, konsol.log ateşlenecek ve çıkış yapacak (zaten benim terminalimde) Thing: { value: 4}, koşulun doğru olduğunu belirterek.

0
Jonathan Kuhl