Catatan Moderator: Harap tahan keinginan untuk mengedit kode atau menghapus pemberitahuan ini. Pola spasi putih mungkin menjadi bagian dari pertanyaan dan karenanya tidak boleh dirusak dengan tidak perlu. Jika Anda berada di camp "whitespace is insignificant", Anda harus dapat menerima kode apa adanya.
Mungkinkah (a== 1 && a ==2 && a==3)
dapat dievaluasi menjadi true
dalam JavaScript?
Ini adalah pertanyaan wawancara yang diajukan oleh perusahaan teknologi besar. Itu terjadi dua minggu yang lalu, tetapi saya masih berusaha menemukan jawabannya. Saya tahu kami tidak pernah menulis kode seperti itu dalam pekerjaan kami sehari-hari, tetapi saya ingin tahu.
Jika Anda memanfaatkan cara kerja ==
, Anda bisa membuat objek dengan fungsi toString
(atau valueOf
) kustom yang mengubah apa yang dikembalikan setiap kali digunakan sehingga memenuhi ketiga kondisi.
const a = {
i: 1,
toString: function () {
return a.i++;
}
}
if(a == 1 && a == 2 && a == 3) {
console.log('Hello World!');
}
Alasan ini berhasil adalah karena penggunaan operator kesetaraan longgar. Saat menggunakan kesetaraan longgar, jika salah satu operan memiliki tipe yang berbeda dari yang lain, mesin akan berusaha untuk mengubah satu ke yang lain. Dalam kasus suatu objek di sebelah kiri dan nomor di sebelah kanan, ia akan berusaha untuk mengkonversi objek ke nomor dengan terlebih dahulu memanggil valueOf
jika itu dapat dipanggil, dan jika gagal itu akan memanggil toString
. Saya menggunakan toString
dalam kasus ini hanya karena itulah yang terlintas dalam pikiran, valueOf
akan lebih masuk akal. Jika saya sebaliknya mengembalikan string dari toString
, mesin kemudian akan berusaha untuk mengubah string ke angka yang memberi kami hasil akhir yang sama, meskipun dengan jalur yang sedikit lebih panjang.
Saya tidak bisa menolak - jawaban lain tidak diragukan lagi benar, tetapi Anda benar-benar tidak dapat berjalan melewati kode berikut:
var aᅠ = 1;
var a = 2;
var ᅠa = 3;
if(aᅠ==1 && a== 2 &&ᅠa==3) {
console.log("Why hello there!")
}
Perhatikan spasi aneh dalam pernyataan if
(yang saya salin dari pertanyaan Anda). Ini adalah Hangul setengah lebar (itu bahasa Korea untuk mereka yang tidak terbiasa) yang merupakan karakter ruang Unicode yang tidak ditafsirkan oleh skrip ECMA sebagai karakter spasi - ini berarti itu adalah karakter yang valid untuk pengidentifikasi. Oleh karena itu ada tiga variabel yang sangat berbeda, satu dengan Hangul setelah a, satu dengan sebelumnya dan yang terakhir hanya dengan a. Mengganti ruang dengan _
agar mudah dibaca, kode yang sama akan terlihat seperti ini:
var a_ = 1;
var a = 2;
var _a = 3;
if(a_==1 && a== 2 &&_a==3) {
console.log("Why hello there!")
}
Lihat validasi pada validator nama variabel Mathias . Jika jarak aneh itu benar-benar dimasukkan dalam pertanyaan mereka, saya yakin itu adalah petunjuk untuk jawaban semacam ini.
Jangan lakukan ini. Serius.
Sunting: Telah menjadi perhatian saya bahwa (walaupun tidak diperbolehkan untuk memulai variabel) Zero-width joiner dan Zero-width non-joiner karakter juga diizinkan dalam nama variabel - lihat Mengaburkan JavaScript dengan karakter nol-lebar - pro dan kontra? .
Ini akan terlihat seperti berikut:
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!")
}
IS MUNGKIN!
var i = 0;
with({
get a() {
return ++i;
}
}) {
if (a == 1 && a == 2 && a == 3)
console.log("wohoo");
}
Ini menggunakan pengambil dalam pernyataan with
untuk membiarkan a
mengevaluasi tiga nilai berbeda.
... ini masih tidak berarti ini harus digunakan dalam kode nyata ...
Lebih buruk lagi, trik ini juga akan berfungsi dengan penggunaan ===
.
var i = 0;
with({
get a() {
return ++i;
}
}) {
if (a !== a)
console.log("yep, this is printed.");
}
Contoh tanpa getter atau valueOf:
a = [1,2,3];
a.join = a.shift;
console.log(a == 1 && a == 2 && a == 3);
Ini berfungsi karena ==
memanggil toString
yang memanggil .join
untuk Array.
Solusi lain, menggunakan Symbol.toPrimitive
yang merupakan ES6 yang setara dengan toString/valueOf
:
let a = {[Symbol.toPrimitive]: ((i) => () => ++i) (0)};
console.log(a == 1 && a == 2 && a == 3);
Jika ditanya apakah mungkin (bukan HARUS), ia dapat meminta "a" untuk mengembalikan nomor acak. Itu akan benar jika menghasilkan 1, 2, dan 3 secara berurutan.
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;
}
}
}
Ketika Anda tidak dapat melakukan apa pun tanpa ekspresi reguler:
var a = {
r: /\d/g,
valueOf: function(){
return this.r.exec(123)[0]
}
}
if (a == 1 && a == 2 && a == 3) {
console.log("!")
}
Ini bekerja karena metode custom valueOf
yang dipanggil ketika Object dibandingkan dengan primitive (seperti Number). Trik utamanya adalah a.valueOf
mengembalikan nilai baru setiap kali karena memanggil exec
pada ekspresi reguler dengan g
flag, yang menyebabkan pembaruan lastIndex
dari ekspresi reguler itu setiap kali ditemukan kecocokan. Jadi pertama kali this.r.lastIndex == 0
, cocok dengan 1
dan pembaruan lastIndex
: this.r.lastIndex == 1
, jadi waktu berikutnya regex akan cocok dengan 2
dan seterusnya.
Itu dapat dicapai dengan menggunakan yang berikut ini dalam lingkup global. Untuk nodejs
gunakan global
daripada window
dalam kode di bawah ini.
var val = 0;
Object.defineProperty(window, 'a', {
get: function() {
return ++val;
}
});
if (a == 1 && a == 2 && a == 3) {
console.log('yay');
}
Jawaban ini menyalahgunakan variabel implisit yang disediakan oleh lingkup global dalam konteks eksekusi dengan mendefinisikan pengambil untuk mengambil variabel.
Ini dimungkinkan jika variabel a
sedang diakses oleh, katakanlah 2 pekerja web melalui SharedArrayBuffer serta beberapa skrip utama. Kemungkinannya rendah, tetapi ada kemungkinan bahwa ketika kode dikompilasi ke kode mesin, pekerja web memperbarui variabel a
tepat pada waktunya sehingga kondisi a==1
, a==2
dan a==3
puas.
Ini bisa menjadi contoh kondisi balapan di lingkungan multi-utas yang disediakan oleh pekerja web dan SharedArrayBuffer dalam JavaScript.
Berikut ini adalah implementasi dasar di atas:
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)
pekerja.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
})
})
Di MacBook Air saya, ini terjadi setelah sekitar 10 miliar iterasi pada upaya pertama:
Usaha kedua:
Seperti yang saya katakan, peluangnya akan rendah, tetapi diberikan waktu yang cukup, itu akan mengenai kondisinya.
Tip: Jika terlalu lama pada sistem Anda. Coba a == 1 && a == 2
dan ubah Math.random()*3
menjadi Math.random()*2
. Menambahkan lebih banyak dan lebih banyak lagi ke daftar akan mengurangi peluang untuk memukul.
Ini juga dimungkinkan dengan menggunakan serangkaian pengambil tulisan sendiri:
(Ini mirip dengan solusi jontro, tetapi tidak memerlukan variabel counter.)
(() => {
"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.");
}
})();
Saya tidak melihat jawaban ini sudah diposting, jadi saya akan memasukkan yang ini ke dalam campuran juga. Ini mirip dengan Jawaban Jeff dengan ruang Hangul setengah lebar.
var a = 1;
var a = 2;
var а = 3;
if(a == 1 && a == 2 && а == 3) {
console.log("Why hello there!")
}
Anda mungkin melihat sedikit perbedaan dengan yang kedua, tetapi yang pertama dan ketiga identik dengan mata telanjang. Semua 3 adalah karakter yang berbeda:
a
- huruf kecil latin Aa
- Lebar Penuh Bahasa Latin huruf kecil Aа
- Huruf kecil Sirilik A
Istilah umum untuk ini adalah "homoglyphs": karakter unicode berbeda yang terlihat sama. Biasanya sulit mendapatkan tiga yang benar-benar tidak dapat dibedakan, tetapi dalam beberapa kasus Anda bisa beruntung. A, Α, А, dan Ꭺ akan bekerja lebih baik (Latin-A, Greek Alpha , Cyrillic-A , dan Cherokee-A masing-masing; sayangnya huruf kecil Yunani dan Cherokee terlalu berbeda dari bahasa Latin a
: α
, ꭺ
, dan karenanya tidak membantu dengan cuplikan di atas).
Ada seluruh kelas Serangan Homoglyph di luar sana, paling umum dalam nama domain palsu (mis. wikipediа.org
(Cyrillic) vs wikipedia.org
(Latin)), tetapi dapat juga muncul dalam kode; biasanya disebut sebagai curang (seperti yang disebutkan dalam komentar, [licik] pertanyaan sekarang di luar topik pada PPCG , tetapi dulu merupakan jenis tantangan di mana hal-hal semacam ini akan menunjukkan naik). Saya menggunakan situs web ini untuk menemukan homoglyph yang digunakan untuk jawaban ini.
Atau, Anda bisa menggunakan kelas untuk itu dan contoh untuk cek.
function A() {
var value = 0;
this.valueOf = function () { return ++value; };
}
var a = new A;
if (a == 1 && a == 2 && a == 3) {
console.log('bingo!');
}
EDIT
Menggunakan kelas ES6 akan terlihat seperti ini
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!');
}
Dalam JavaScript, tidak ada integer tetapi hanya Number
s, yang diimplementasikan sebagai angka floating point presisi ganda.
Ini berarti bahwa jika suatu Angka a
cukup besar, itu dapat dianggap sama dengan tiga bilangan bulat berturut-turut:
a = 100000000000000000
if (a == a+1 && a == a+2 && a == a+3){
console.log("Precision loss!");
}
Benar, itu tidak persis apa yang diminta pewawancara (tidak bekerja dengan a=0
), tetapi tidak melibatkan trik dengan fungsi tersembunyi atau kelebihan operator.
Untuk referensi, ada solusi a==1 && a==2 && a==3
di Ruby dan Python. Dengan sedikit modifikasi, itu juga mungkin di Jawa.
Dengan ==
khusus:
class A
def ==(o)
true
end
end
a = A.new
if a == 1 && a == 2 && a == 3
puts "Don't do this!"
end
Atau a
yang semakin meningkat:
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!")
Dimungkinkan untuk memodifikasi Java Integer
cache :
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.");
}
}
}
if=()=>!0;
var a = 9;
if(a==1 && a== 2 && a==3)
{
document.write("<h1>Yes, it is possible!????</h1>")
}
Kode di atas adalah versi singkat (terima kasih kepada @Forivin untuk catatannya di komentar) dan kode berikut ini asli:
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;}
Jika Anda hanya melihat sisi atas kode saya dan menjalankannya, Anda katakan WOW, bagaimana?
Jadi saya pikir sudah cukup untuk mengatakan Ya, itu mungkin kepada seseorang yang berkata kepada. Anda: Tidak ada yang mustahil
Trik: Saya menggunakan karakter tersembunyi setelah
if
untuk membuat fungsi yang namanya mirip denganif
. Di JavaScript kita tidak bisa mengesampingkan kata kunci jadi saya terpaksa menggunakan cara ini. Ini adalahif
palsu, tetapi ini berfungsi untuk Anda dalam kasus ini!
Saya juga menulis versi C # (dengan peningkatan nilai properti teknik):
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!????");
}
}
Ini adalah versi terbalik dari @ Jeff's jawaban * di mana karakter tersembunyi (U + 115F, U + 1160 atau U + 3164) digunakan untuk membuat variabel yang terlihat seperti 1
, 2
dan 3
.
var a = 1;
var ᅠ1 = a;
var ᅠ2 = a;
var ᅠ3 = a;
console.log( a ==ᅠ1 && a ==ᅠ2 && a ==ᅠ3 );
* Jawaban itu dapat disederhanakan dengan menggunakan non-joiner lebar nol (U + 200C) dan joiner lebar nol (U + 200D). Kedua karakter ini diizinkan di dalam pengidentifikasi tetapi tidak di awal:
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);
****/
Trik lain dimungkinkan menggunakan ide yang sama mis. dengan menggunakan pemilih variasi Unicode untuk membuat variabel yang terlihat persis sama (a︀ = 1; a︁ = 2; a︀ == 1 && a︁ == 2; // true
).
Peraturan nomor satu wawancara; tidak pernah mengatakan tidak mungkin.
Tidak perlu tipuan karakter tersembunyi.
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?' );
}
Jujur saja, apakah ada cara untuk mengevaluasi untuk benar atau tidak (dan seperti yang telah ditunjukkan orang lain, ada beberapa cara), jawaban yang saya cari, berbicara sebagai seseorang yang telah melakukan ratusan wawancara, akan menjadi sesuatu di sepanjang baris:
"Yah, mungkin ya dalam beberapa keadaan aneh yang tidak segera jelas bagi saya ... tetapi jika saya menemukan ini dalam kode nyata maka saya akan menggunakan teknik debugging umum untuk mencari tahu bagaimana dan mengapa ia melakukan apa yang dilakukannya dan kemudian segera refactor kode untuk menghindari situasi itu ... tetapi yang lebih penting: Saya benar-benar TIDAK akan pernah menulis kode itu di tempat pertama karena itu adalah definisi kode berbelit-belit, dan saya berusaha untuk tidak pernah menulis kode berbelit-belit ".
Saya kira beberapa pewawancara akan tersinggung untuk memiliki apa yang jelas-jelas dimaksudkan sebagai pertanyaan yang sangat rumit, tetapi saya tidak keberatan pengembang yang memiliki pendapat, terutama ketika mereka dapat mendukungnya dengan pemikiran yang masuk akal dan dapat menyelaraskan pertanyaan saya menjadi pernyataan yang bermakna tentang diri mereka sendiri.
Berikut variasi lain, menggunakan array untuk memunculkan nilai apa pun yang Anda inginkan.
const a = {
n: [3,2,1],
toString: function () {
return a.n.pop();
}
}
if(a == 1 && a == 2 && a == 3) {
console.log('Yes');
}
Jika Anda pernah mendapatkan pertanyaan wawancara semacam itu (atau perhatikan beberapa perilaku yang sama sekali tidak terduga dalam kode Anda) pikirkan tentang hal-hal apa yang dapat menyebabkan perilaku yang terlihat mustahil pada pandangan pertama:
Pengkodean: Dalam hal ini variabel yang Anda lihat bukan yang Anda pikirkan. Ini bisa terjadi jika Anda sengaja dipusingkan dengan Unicode menggunakan homoglyphs atau karakter spasi untuk membuat nama variabel terlihat seperti yang lain, tetapi masalah penyandian juga dapat diperkenalkan secara tidak sengaja, mis. saat menyalin & menempelkan kode dari Web yang berisi titik kode Unicode yang tidak terduga (mis. karena sistem manajemen konten melakukan beberapa "pemformatan otomatis" seperti mengganti fl
dengan Unicode 'LATIN SMALL LIGATURE FL' (U + FB02)).
Kondisi ras: A kondisi ras mungkin terjadi, yaitu situasi di mana kode tidak dieksekusi dalam urutan yang diharapkan oleh pengembang. Kondisi balapan sering terjadi dalam kode multi-ulir, tetapi beberapa utas bukan merupakan persyaratan agar kondisi balapan dimungkinkan - asinkronisitas sudah cukup (dan jangan bingung, async tidak berarti beberapa utas digunakan di bawah tenda ).
Perhatikan bahwa karena itu JavaScript juga tidak bebas dari kondisi balapan hanya karena itu adalah single-threaded. Lihat di sini untuk contoh single-threaded sederhana - tetapi async -. Namun dalam konteks pernyataan tunggal, kondisi balapan akan agak sulit dicapai di JavaScript.
JavaScript dengan pekerja web sedikit berbeda, karena Anda dapat memiliki banyak utas. @mehulmpt telah menunjukkan kepada kami proof-of-concept menggunakan pekerja web .
Efek samping: Efek samping dari operasi perbandingan kesetaraan (yang tidak harus sejelas dalam contoh di sini, seringkali efek samping sangat halus).
Masalah-masalah semacam ini dapat muncul dalam banyak bahasa pemrograman, tidak hanya JavaScript, jadi kami tidak melihat salah satu dari klasik JavaScript WTF di sini1.
Tentu saja, pertanyaan wawancara dan sampel di sini semua terlihat sangat dibuat-buat. Tetapi mereka adalah pengingat yang baik bahwa:
1 Sebagai contoh, Anda dapat menemukan contoh dalam bahasa pemrograman yang sangat berbeda (C #) menunjukkan efek samping (yang jelas) di sini .
Oke, peretasan lain dengan generator:
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!');
}
Sebenarnya jawaban untuk bagian pertama dari pertanyaan adalah "Ya" di setiap bahasa pemrograman. Misalnya, ini dalam kasus 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;
}
Menggunakan Proxy :
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 pada dasarnya berpura-pura menjadi objek target (parameter pertama), tetapi mencegat operasi pada objek target (dalam hal ini operasi "dapatkan properti") sehingga ada peluang untuk melakukan sesuatu selain perilaku objek default. Dalam hal ini tindakan "dapatkan properti" dipanggil pada a
ketika ==
memaksa jenisnya untuk membandingkannya dengan setiap nomor. Ini terjadi:
{ i: 0 }
, di mana properti i
adalah counter kamia
a ==
, tipe a
dipaksa ke nilai primitifa[Symbol.toPrimitive]()
secara internala[Symbol.toPrimitive]
menggunakan "get handler"Symbol.toPrimitive
, yang dalam hal ini bertambah dan kemudian mengembalikan penghitung dari objek target: ++target.i
. Jika properti lain sedang diambil, kami kembali ke mengembalikan nilai properti default, target[name]
Begitu:
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
Seperti sebagian besar jawaban lainnya, ini hanya berfungsi dengan pemeriksaan kesetaraan longgar (==
), karena pemeriksaan kesetaraan yang ketat (===
) tidak melakukan jenis paksaan yang dapat disadap oleh Proxy.
Sama, tetapi berbeda, tetapi tetap sama (dapat "diuji" beberapa kali):
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!');
}
Ide saya mulai dari bagaimana persamaan tipe objek Nomor bekerja.
Jawaban ECMAScript 6 yang memanfaatkan Simbol:
const a = {value: 1};
a[Symbol.toPrimitive] = function() { return this.value++ };
console.log((a == 1 && a == 2 && a == 3));
Karena penggunaan ==
, JavaScript seharusnya memaksa a
menjadi sesuatu yang dekat dengan operan kedua (1
, 2
, 3
dalam kasus ini). Tetapi sebelum JavaScript mencoba mencari paksaan dengan sendirinya, ia mencoba memanggil Symbol.toPrimitive
. Jika Anda memberikan Symbol.toPrimitive
JavaScript akan menggunakan nilai yang dikembalikan fungsi Anda. Jika tidak, JavaScript akan memanggil valueOf
.
Saya pikir ini adalah kode minimal untuk mengimplementasikannya:
i=0,a={valueOf:()=>++i}
if (a == 1 && a == 2 && a == 3) {
console.log('Mind === Blown');
}
Membuat objek dummy dengan valueOf
kustom yang menambah variabel global i
pada setiap panggilan. 23 karakter!
Yang ini menggunakan defineProperty dengan efek samping yang bagus yang menyebabkan variabel global!
var _a = 1
Object.defineProperty(this, "a", {
"get": () => {
return _a++;
},
configurable: true
});
console.log(a)
console.log(a)
console.log(a)
Dengan mengganti valueOf
dalam deklarasi kelas, itu dapat dilakukan:
class Thing {
constructor() {
this.value = 1;
}
valueOf() {
return this.value++;
}
}
const a = new Thing();
if(a == 1 && a == 2 && a == 3) {
console.log(a);
}
Apa yang terjadi adalah bahwa valueOf
dipanggil di setiap operator perbandingan. Pada yang pertama, a
akan sama dengan 1
, pada yang kedua, a
akan sama dengan 2
, dan seterusnya dan seterusnya, karena setiap kali valueOf
disebut, nilai a
akan bertambah.
Oleh karena itu console.log akan aktif dan menghasilkan (di terminal saya) Thing: { value: 4}
, yang menunjukkan bahwa kondisional itu benar.