Có thể (a == 1 && a == 2 && a == 3) có thể đánh giá là đúng không?


2484

Người điều hành lưu ý: Vui lòng chống lại sự thôi thúc chỉnh sửa mã hoặc xóa thông báo này. Mô hình của khoảng trắng có thể là một phần của câu hỏi và do đó không nên bị can thiệp một cách không cần thiết. Nếu bạn đang ở trong trại "khoảng trắng là không đáng kể", bạn sẽ có thể chấp nhận mã như hiện tại.

Có bao giờ có (a== 1 && a ==2 && a==3)thể đánh giá truetrong JavaScript?

Đây là một câu hỏi phỏng vấn được hỏi bởi một công ty công nghệ lớn. Nó đã xảy ra hai tuần trước, nhưng tôi vẫn đang cố gắng tìm câu trả lời. Tôi biết chúng tôi không bao giờ viết mã như vậy trong công việc hàng ngày của mình, nhưng tôi tò mò.


9
Bình luận không dành cho thảo luận mở rộng; cuộc trò chuyện này đã được chuyển sang trò chuyện .
lừa dối

109
Đối với những người dường như đã bỏ phiếu cho điều này là quá rộng : đó có phải là một đào tại Javascript, nói rằng có quá nhiều câu trả lời hợp lệ?
tomsmeding

24
Một số người ngồi xung quanh triết lý về những gì có thể. Những người khác tập trung nỗ lực của họ vào việc họ có đang xây dựng các sản phẩm chính xác, khả thi cho khách hàng hay không. IMO, câu hỏi này không có tiện ích thiết thực nào ngoài thực tế là bạn không bao giờ nên hỏi những loại câu hỏi này trong một cuộc phỏng vấn hoặc viết loại mã này. Đó là lý do tại sao nó nên được đóng lại. Ý tôi thực sự là, doanh nghiệp có nhận ra họ đã trả cho ai đó tiền thật để ngồi xung quanh và nói về những thứ này không?
P.Brian.Mackey

15
Sau khi đọc câu trả lời, đạo đức của câu chuyện là: không sử dụng ==khi bạn muốn nói ===, có một tiêu chuẩn mã hóa cấm các tên biến không phải ASCII và có một quy trình linting thực thi hai đạo đức trước đó.
Jesse C. Choper

87
Người điều hành lưu ý: Stack Overflow đã có một lịch sử về những người đang tìm kiếm câu trả lời bằng các ngôn ngữ khác nhau cho câu hỏi. Đây những nỗ lực để trả lời câu hỏi vì chúng là giải pháp cho vấn đề chung, mặc dù trong một ngôn ngữ khác. Xin vui lòng không gắn cờ họ là "không phải là một câu trả lời". Đã nói rằng, xin vui lòng không đăng thêm câu trả lời bằng các ngôn ngữ khác nhau - có một lý do câu hỏi này dành riêng cho JavaScript, như được chỉ ra bởi các nhận xét dưới một số câu trả lời khác này và có một lý do chúng tôi thích các câu hỏi dành riêng cho ngôn ngữ của chúng tôi vẫn như vậy
BoltClock

Câu trả lời:


3323

Nếu bạn tận dụng cách thức ==hoạt động , bạn có thể chỉ cần tạo một đối tượng với hàm tùy chỉnh toString(hoặc valueOf) thay đổi những gì nó trả về mỗi khi nó được sử dụng sao cho nó thỏa mãn cả ba điều kiện.

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

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


Lý do công việc này là do việc sử dụng toán tử đẳng thức lỏng lẻo. Khi sử dụng đẳng thức lỏng lẻo, nếu một trong các toán hạng có loại khác với loại khác, động cơ sẽ cố gắng chuyển đổi loại này sang loại khác. Trong trường hợp một đối tượng ở bên trái và một số ở bên phải, nó sẽ cố gắng chuyển đổi đối tượng thành một số bằng cách gọi đầu tiên valueOfnếu nó có thể gọi được và không thực hiện được, nó sẽ gọi toString. Tôi đã sử dụng toStringtrong trường hợp này đơn giản vì đó là những gì tôi nghĩ đến, valueOfsẽ có ý nghĩa hơn. Thay vào đó, nếu tôi trả về một chuỗi từ toString, thì động cơ đã cố gắng chuyển đổi chuỗi thành một số cho chúng ta kết quả cuối cùng, mặc dù với đường dẫn dài hơn một chút.


70
Bạn có thể đạt được điều này bằng cách thay đổi valueOf()hoạt động ngụ ý ?
Sterling Archer

43
Có, valueOf hoạt động thay cho toString vì lý do tương tự
Kevin B

4
Bình luận không dành cho thảo luận mở rộng; cuộc trò chuyện này đã được chuyển sang trò chuyện .
lừa dối

13
Theo đó, một chuyển đổi số sẽ được thử trước tiên nên valueOftốt hơn một chút.
Salman A

6
@Pureferret phía bên trái của so sánh bình đẳng là một đối tượng, không phải là một số. Đối tượng đó có thuộc tính số ikhông làm phiền động cơ. ;)
tomsmeding

2057

Tôi không thể cưỡng lại - những câu trả lời khác chắc chắn là đúng, nhưng bạn thực sự không thể bỏ qua đoạn mã sau:

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

Lưu ý khoảng cách kỳ lạ trong ifcâu lệnh (mà tôi đã sao chép từ câu hỏi của bạn). Đó là Hangul nửa chiều rộng (tiếng Hàn dành cho những người không quen thuộc) là ký tự không gian Unicode không được giải thích bởi tập lệnh ECMA dưới dạng ký tự khoảng trắng - điều này có nghĩa là ký tự hợp lệ cho mã định danh. Do đó, có ba biến hoàn toàn khác nhau, một biến có Hangul sau a, một biến trước và biến cuối chỉ có a. Thay thế không gian bằng _để dễ đọc, cùng một mã sẽ như thế này:

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

Kiểm tra xác nhận trên trình xác nhận tên biến của Mathias . Nếu khoảng cách kỳ lạ đó thực sự được bao gồm trong câu hỏi của họ, tôi cảm thấy chắc chắn rằng đó là một gợi ý cho loại câu trả lời này.

Đừng làm điều này. Nghiêm túc.

Edit: Nó đã gây chú ý của tôi đó (mặc dù không được phép bắt đầu biến) các sản phẩm mộc Zero-chiều rộngZero-width phi joiner nhân vật cũng được cho phép trong tên biến - xem obfuscating JavaScript với zero-width ký tự - ưu và nhược điểm ? .

Điều này sẽ trông như sau:

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
Đánh giá theo khoảng cách lẻ trong câu hỏi ban đầu, tôi nghĩ rằng đây chính xác là câu trả lời mà câu hỏi phỏng vấn đang tìm kiếm - khai thác các ký tự không phải không gian trông giống như khoảng trắng. Điểm tốt!
Baracus

18
@Baracus Chính RonJohn đã nhận thấy khoảng cách kỳ lạ trong nhận xét của anh ấy về câu trả lời của Kevin đã nhắc nhở tôi về kỹ thuật (khủng khiếp) này, vì vậy tôi không thể tin vào việc phát hiện ra nó. Mặc dù vậy, tôi rất ngạc nhiên khi không có ai trả lời về vấn đề này, vì nó đã xảy ra xung quanh công việc của tôi vài năm trước vì một bài đăng trên blog ở đâu đó - tôi cho rằng bây giờ nó là kiến ​​thức khá phổ biến.
Jeff

102
Tất nhiên, điều này bị cấm như một lỗ hổng tiêu chuẩn , cũng áp dụng cho các cuộc phỏng vấn. [cần dẫn nguồn]
Sanchise

13
Xem xét khoảng cách ban đầu, nó có thể còn tồi tệ hơn, tức là một biến var ᅠ2 = 3đã được sử dụng; vì vậy có ba biến số aᅠᅠ= 1, ᅠ2 = 3, a = 3( a␣ = 1, ␣2 = 3, a = 3vì vậy (a␣==1 && a==␣2 && a==3)))
Holger

2
@ AL-zami có một ký tự phụ ở hai trong số các biến, hiển thị trên màn hình của bạn dưới dạng khoảng trắng, nhưng được hiểu là một phần của mã định danh, có nghĩa là có ba biến riêng biệt - a, a và a - ký tự phụ là không gian nửa chiều rộng Hangul.
Jeff

620

ĐIỀU ĐÓ LÀ CÓ THỂ!

var i = 0;

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

Điều này sử dụng một getter bên trong một withcâu lệnh để cho phép ađánh giá theo ba giá trị khác nhau.

... điều này vẫn không có nghĩa là điều này nên được sử dụng trong mã thực ...

Thậm chí tệ hơn, thủ thuật này cũng sẽ hoạt động với việc sử dụng ===.

  var i = 0;

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


65
Có, tôi đã thử điều tương tự :) Vì vậy, câu trả lời chính xác trong cuộc phỏng vấn sẽ là "Nó không thể xảy ra trong mã của tôi vì tôi không bao giờ sử dụng with."
Mũi nhọn

7
@Pointy - Và, tôi lập trình ở chế độ nghiêm ngặt withkhông được phép.
jfriend00

6
@Pointy trong câu trả lời được chấp nhận họ làm điều gì đó tương tự mà không có withđiều đó có thể xảy ra
Jungkook

2
@jorrit không ai dùng ==. Và ===ngăn câu trả lời được chấp nhận
Jonas Wilms

4
@JasasW. Rất nhiều người vẫn sử dụng ==nhưng tôi chưa từng thấy withvì ... thực sự không bao giờ nằm ​​ngoài tài liệu JS có ghi "làm ơn đừng sử dụng nó". Dù sao, một giải pháp tốt đẹp.
wortwart

516

Ví dụ không có getters hoặc valueOf:

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

Này hoạt động vì ==gọi toStringmà các cuộc gọi .joincho Mảng.

Một giải pháp khác, sử dụng Symbol.toPrimitivetương đương ES6 là toString/valueOf:

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

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


9
without valueOf, tốt ... nó gián tiếp hơn nhưng về cơ bản là điều tương tự.
Jonas Wilms

11
Tôi thực sự thích giải pháp này vì bạn không ghi đè lên bất cứ thứ gì ngoại trừ chức năng tham gia của các đối tượng và nó chỉ là một bản hack rất sạch và dễ đọc khiến logic đánh giá thành đúng.
Alex Pedersen

28
Thành thật tôi nghĩ rằng đây là câu trả lời tốt nhất. Nó không liên quan gì đến bình thường, chỉ cần thiết lập một vài giá trị. Rất dễ hiểu ngay cả với kiến ​​thức cơ bản về JS. Làm tốt.
Zac Delventhal

14
Điều này làm cho rất nhiều ý nghĩa nó gần như cảm thấy hữu ích.
Andrew

7
Tôi biết hầu hết các câu trả lời sẽ là về việc lạm dụng toStringhoặc valueOfnhưng câu trả lời này khiến tôi hoàn toàn mất cảnh giác. Rất thông minh và tôi không biết nó đã gọi .joinnội bộ, nhưng nó hoàn toàn có ý nghĩa.
GBarroso

268

Nếu được hỏi nếu có thể (không PHẢI), nó có thể yêu cầu "a" trả về một số ngẫu nhiên. Nó sẽ đúng nếu nó tạo 1, 2 và 3 tuần tự.

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
Tôi sẽ cố tình đưa ra câu trả lời này ngay cả khi tôi biết các giải pháp khác, bởi vì nó trả lời câu hỏi nhưng rõ ràng không phải là những gì họ đã theo sau. Chơi các trò chơi ngu ngốc, giành giải thưởng ngu ngốc.
ESR

2
Nhưng nếu phải mất hơn 1000 thử nghiệm thì sao?
Phiên âm

9
@Piyin Nếu phải mất hơn 1000 thử nghiệm, bạn sẽ giành được giải thưởng!
Xiên

5
Tôi thích câu trả lời này bởi vì đưa nó đến mức cực đoan cho thấy rằng điều này có thể xảy ra trong bất kỳ ngôn ngữ nào nếu các thanh ghi / bộ đệm của cpu bị va chạm với đủ các tia vũ trụ trong khi chương trình đang chạy hoặc nếu một người cố tình thực hiện một sự cố điện sao cho nhánh thất bại của nếu điều kiện không thực sự nhảy.
Ponkadoodle

Thấp nhất: 1, Cao nhất: 412.
KyleFairns

210

Khi bạn không thể làm bất cứ điều gì mà không có biểu thức thông thường:

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

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

Nó hoạt động vì tùy chỉnh valueOf phương thức được gọi khi Object so với nguyên thủy (như Number). Thủ thuật chính là a.valueOftrả về giá trị mới mỗi lần vì nó gọi execbiểu thức chính quy bằng gcờ, điều này gây ra việc cập nhật lastIndexbiểu thức chính quy đó mỗi khi tìm thấy kết quả khớp. Vì vậy, lần đầu tiên this.r.lastIndex == 0, nó phù hợp 1và cập nhật lastIndex: this.r.lastIndex == 1, vì vậy thời gian tiếp theo regex sẽ phù hợp 2và như vậy.


22
@Abdillah một đối tượng regex sẽ nhớ chỉ mục cuối cùng mà nó khớp, gọi execlại sẽ bắt đầu tìm kiếm từ chỉ mục đó. MDN không rõ ràng lắm.
Simon Chan

Tôi thấy, vì vậy this.rđối tượng regex nhớ trạng thái / chỉ mục. Cảm ơn!
Abdillah

Tôi khuyên bạn nên chuyển một chuỗi đến execmặc dù không phải là một số nguyên được xâu chuỗi .
Bergi

sử dụng regex và bây giờ bạn có hai vấn đề
Aleksey Solovey

191

Nó có thể được thực hiện bằng cách sử dụng sau đây trong phạm vi toàn cầu. Để nodejssử dụng globalthay vì windowtrong mã dưới đây.

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

Câu trả lời này lạm dụng các biến ẩn được cung cấp bởi phạm vi toàn cục trong ngữ cảnh thực thi bằng cách xác định một getter để truy xuất biến.


Giả định anày là một tài sản thismà nó dường như không phải là. Nếu alà một biến cục bộ (trông giống như vậy), thì nó sẽ không hoạt động.
jfriend00

1
@ jfriend00 ý bạn là nếu bạn đặt var a; một vài nơi?
jontro

Vâng. Tham chiếu a == 1ngụ ý hơn alà một biến ở đâu đó, không phải là một thuộc tính của this. Mặc dù có một vị trí kỳ quặc như toàn cầu, nơi cả hai đều có thể đúng, nói chung, việc khai báo một biến có var ahoặc let acó nghĩa là không có thischo phép bạn truy cập anhư một tài sản như mã của bạn giả định. Vì vậy, mã của bạn rõ ràng là giả định một số điều biến toàn cầu kỳ lạ. Ví dụ: mã của bạn không hoạt động trong node.js và không ở chế độ nghiêm ngặt bên trong một hàm. Bạn nên xác định chính xác các trường hợp hoạt động và có thể giải thích lý do tại sao nó hoạt động. Nếu không, nó gây hiểu nhầm.
jfriend00

@ jfriend00 cũng chắc chắn. Không chắc chắn rằng nó sẽ thêm nhiều giá trị hơn kết hợp với các câu trả lời đã có khác. Sẽ cập nhật câu trả lời
jontro

14
Câu hỏi là, "bao giờ" có thể là sự thật. Và câu trả lời là có, và đây là một trong những tình huống có thể đúng: akhông phải là biến cục bộ và được xác định trên phạm vi toàn cầu với một getter tăng dần.
Zac Delventhal

190

Điều này có thể xảy ra trong trường hợp biến ađược truy cập bởi, giả sử 2 nhân viên web thông qua SharedArrayBuffer cũng như một số tập lệnh chính. Khả năng là thấp, nhưng nó có thể là khi mã được biên dịch sang mã máy, các công nhân trang web cập nhật các biến achỉ trong thời gian như vậy điều kiện a==1, a==2a==3 được thỏa mãn.

Đây có thể là một ví dụ về điều kiện chủng tộc trong môi trường đa luồng được cung cấp bởi các nhân viên web và SharedArrayBuffer trong JavaScript.

Đây là cách thực hiện cơ bản ở trên:

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

Trên MacBook Air của tôi, nó xảy ra sau khoảng 10 tỷ lần lặp lại trong lần thử đầu tiên:

nhập mô tả hình ảnh ở đây

Lần thử thứ hai:

nhập mô tả hình ảnh ở đây

Như tôi đã nói, cơ hội sẽ thấp, nhưng nếu có đủ thời gian, nó sẽ đạt được điều kiện.

Mẹo: Nếu mất quá nhiều thời gian trên hệ thống của bạn. Chỉ thử a == 1 && a == 2và thay đổi Math.random()*3thành Math.random()*2. Thêm nhiều hơn và nhiều hơn vào danh sách giảm cơ hội đánh.


50
Thành thật mà nói, đây là câu trả lời tốt nhất. Tất cả các câu trả lời khác đòi hỏi một nỗ lực cố ý để làm một cái gì đó sâu sắc không trực quan. Câu trả lời này thực sự phản ánh điều gì đó có thể xảy ra trong thế giới thực - một điều kiện chủng tộc.
Tom Swirly

34
Không chỉ vậy - tôi thực sự đã thấy điều này xảy ra trong thế giới thực. Không phải với điều kiện chính xác trong câu hỏi, nhưng chắc chắn với việc kiểm tra (a == 1) khi bắt đầu hàm và (a == 2) sau đó trong hàm và có mã đạt cả hai điều kiện. FYI, lần đầu tiên tôi thấy điều này xảy ra là trong một bộ điều khiển động cơ xe hơi, và chúng tôi đã áp dụng các tiêu chuẩn mã hóa. Lần thứ hai là trong một hệ thống phân phối chaff và flare cho máy bay quân sự, và vào ngày đầu tiên ở công ty tôi đã tìm thấy nó và sửa nó, trong khi các thành viên còn lại vẫn đang thảo luận về vấn đề này. (Cấp độ của Kudos: cao! :)
Graham

38
Vì vậy, bạn đã làm việc trên "bộ điều khiển động cơ xe hơi" và "hệ thống phân phối chaff và flare" được lập trình trong javascript với nhân viên web? Tôi không nghĩ rằng tôi sẽ ra ngoài một lần nữa.
psaxton

12
@psaxton :) Tất nhiên là không - nhưng chúng tôi có phần mềm đa luồng với dữ liệu được chia sẻ. Đây là một mô hình chống cho tất cả các phần mềm đa luồng, không dành riêng cho Javascript hoặc cho nhân viên web. Không quan trọng bạn đang lập trình bằng ngôn ngữ lắp ráp, Brainf * ck, Visual BASIC, C hoặc Javascript - nếu bạn làm điều này với dữ liệu được chia sẻ trong một ứng dụng đa luồng, nó sẽ luôn thất bại.
Graham

4
Tôi nghĩ rằng đây là một trình bao bọc công phu xung quanh câu trả lời của @ jontro.
qntm

148

Điều này cũng có thể sử dụng một loạt các getters tự ghi đè:

(Điều này tương tự như giải pháp của jontro, nhưng không yêu cầu biến đếm.)

(() => {
    "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
Lưu ý rằng phương pháp sử dụng getter cũng hoạt động với ===, không chỉ ==.
Makyen

Giải pháp này dựa vào thisviệc là đối tượng toàn cầu bên trong cơ thể của chức năng mũi tên.
Roy Tinker

@Unnightas Tôi sẽ không phân loại bất kỳ câu trả lời nào khác là "mã kim tự tháp" .
Patrick Roberts

Lưu ý điều này cũng hoạt động với thứ tự tùy ý, phải không? Giống như (a == 3 && a == 2 && a == 1)?
Johannes

131

Ngoài ra, bạn có thể sử dụng một lớp cho nó và một thể hiện cho kiểm tra.

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

var a = new A;

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

BIÊN TẬP

Sử dụng các lớp ES6 nó sẽ trông như thế này

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
chỉ function A() {value = 0;lúc bắt đầu?
Dave C

valueOfđang bị ghi đè, this method is usually called automatically by JavaScript behind the scenes, and not explicitly in codevì vậy khi chúng ta so sánh giá trị nó thực sự tăng lên một ..
Danyal Sandeelo

130

Tôi không thấy câu trả lời này đã được đăng, vì vậy tôi cũng sẽ đưa câu trả lời này vào hỗn hợp. Điều này tương tự như câu trả lời của Jeff với không gian Hangul nửa chiều rộng.

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

Bạn có thể nhận thấy một sự khác biệt nhỏ với cái thứ hai, nhưng cái thứ nhất và thứ ba giống hệt với mắt thường. Cả 3 đều là những ký tự riêng biệt:

a- Chữ thường chữ
A A
а- Chữ thường chữ A chữ thường A - Chữ thường chữ A

Thuật ngữ chung cho điều này là "homoglyphs": các ký tự unicode khác nhau trông giống nhau. Thông thường khó có được ba thứ hoàn toàn không thể phân biệt được, nhưng trong một số trường hợp bạn có thể gặp may mắn. A,, А và sẽ hoạt động tốt hơn (tiếng Latin-A, Hy Lạp Alpha , Cyrillic-A , và Cherokee-A tương ứng; tiếc là Hy Lạp và Cherokee thấp hơn trường hợp chữ quá khác nhau từ tiếng Latinh a: α, , và do đó doesn 't giúp với đoạn trích trên).

Có cả một nhóm Tấn công Homoglyph ngoài kia, phổ biến nhất là trong các tên miền giả (ví dụ: wikipediа.org(Cyrillic) vs wikipedia.org(Latin)), nhưng nó cũng có thể hiển thị theo mã; thường được gọi là bị lén lút (như được đề cập trong một bình luận, các câu hỏi [ngầm] bây giờ không có chủ đề PPCG , nhưng đã từng là một loại thử thách mà những thứ như thế sẽ xuất hiện). Tôi đã sử dụng trang web này để tìm các homoglyphs được sử dụng cho câu trả lời này.


19
"Sự khác biệt nhỏ" không phải là cách tôi sẽ gọi nó.

4
@hvd Hoàn toàn phụ thuộc vào kết xuất phông chữ của bạn. Đây là những gì tôi thấy .
Draco18 không còn tin tưởng SE

1
@Jake Vâng, chữ thường Latin toàn chữ A không phải là từ đồng âm lớn nhất (nhưng các biến thể chữ in hoa là tuyệt vời). Nói chung mặc dù bạn chỉ cần hai để có được hiệu quả mong muốn.
Draco18 không còn tin tưởng SE

@ Draco18s Đồng ý lại: chỉ cần 2 thường. Tốt công việc trên các thông tin thêm quá!
JakeSteam

10
Bạn cũng có thể sử dụng bộ chọn biến thể unicode (U + FE00..U + FE0F). Không ai trong số này là a: a︀ a︁ a︂. Không còn lo lắng về sự khác biệt.
Salman A

108

Vâng, nó là có thể! 😎

»JavaScript

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

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

Đoạn mã trên là một phiên bản ngắn (nhờ @Forivin đã ghi chú trong phần bình luận) và đoạn mã sau là bản gốc:

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

Nếu bạn chỉ nhìn thấy mặt trên của mã của tôi và chạy nó, bạn nói WOW, làm thế nào?

Vì vậy, tôi nghĩ rằng đủ để nói Có, có thể với ai đó đã nói với bạn: Không có gì là không thể

Thủ thuật: Tôi đã sử dụng một ký tự ẩn sau đó ifđể tạo một hàm có tên tương tự if. Trong JavaScript, chúng tôi không thể ghi đè từ khóa nên tôi buộc phải sử dụng cách này. Nó là giả if, nhưng nó hoạt động cho bạn trong trường hợp này!


» C #

Ngoài ra tôi đã viết một phiên bản C # ( với kỹ thuật tăng giá trị tài sản ):

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

Bản thử trực tiếp


56
Phiên bản javascript là một tội ác thực sự chống lại loài người và khả năng thực hiện điều này, nên là bất hợp pháp bởi các công ước của Liên Hợp Quốc. Tôi nghĩ rằng đã đến lúc chúng ta thanh lọc thế giới của tất cả các kiến ​​thức về javacript.
Rõ ràng hơn

2
Khai báo hàm có thể thậm chí ngắn hơn. if‌=()=>!0
Forivin

4
Tại sao bạn lại sử dụng document.write? Đó là một cách chắc chắn để không được thuê bất kể phần còn lại của câu trả lời.
Cerbrus

3
@Cerbrus, Cảm ơn bạn đã lưu ý. Tôi đã viết câu trả lời đầu tiên của mình với console.lognhưng tôi đã thay đổi nó thành document.write. Thực sự tôi luôn sử dụng console.logmã của mình nhưng ở đây tôi chỉ muốn hiển thị văn bản cho người dùng trong hộp đoạn mã StackOverflow. Vì vậy, tôi muốn hiển thị thông điệp của mình đẹp hơn thông điệp được tạo bởi console.log. Nhấp vào Run Code Snippetnút trên câu trả lời của tôi và các câu trả lời khác. Đoạn mã SO cho phép tôi sử dụng html và JS và CSS sau đó tôi muốn sử dụng nó trong câu trả lời của mình và làm cho nó hay. Tôi nghĩ rằng nó không có bất kỳ tác dụng phụ tiêu cực nào và không làm cho câu trả lời của tôi trở nên lớn hoặc bị phàn nàn.
RAM

1
@Clearer, Nếu các Công ước của Liên hợp quốc có thể thay đổi thế giới một cách hiệu quả, thì chúng ta nên có một thế giới tốt hơn thế này. Chúng tôi cần nhiều thứ hơn là tuyên bố tại Liên Hợp Quốc và cho đến ngày đó tôi nghĩ rằng chúng tôi có thể sử dụng thủ thuật Javascript này của tôi;)
RAM

97

JavaScript

a == a +1

Trong JavaScript, không có số nguyên mà chỉ có Numbers, được triển khai dưới dạng số dấu phẩy động chính xác kép.

Điều đó có nghĩa là nếu một Số ađủ lớn, nó có thể được coi là bằng ba số nguyên liên tiếp:

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

Đúng, đó không chính xác là những gì người phỏng vấn đã hỏi (nó không hoạt động a=0), nhưng nó không liên quan đến bất kỳ thủ thuật nào với chức năng ẩn hoặc quá tải toán tử.

Những ngôn ngữ khác

Để tham khảo, có a==1 && a==2 && a==3các giải pháp trong Ruby và Python. Với một sửa đổi nhỏ, nó cũng có thể có trong Java.

Hồng ngọc

Với một tùy chỉnh ==:

class A
  def ==(o)
    true
  end
end

a = A.new

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

Hoặc tăng a:

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

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

Con trăn

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

Có thể sửa đổi Integerbộ đệm Java :

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 :) Đã có đủ câu trả lời JS tốt. Tôi chỉ nghĩ rằng sẽ rất thú vị khi chỉ ra cách nó có thể được thực hiện bằng các ngôn ngữ khác và có thể cung cấp cho các nhà phát triển JS một số ý tưởng.
Eric Duminil

2
@ cᴏʟᴅsᴘᴇᴇᴅ: Được cập nhật với một ví dụ về JS.
Eric Duminil

1
Tại sao phiên bản Java không hoạt động với Integer a = 42(hoặc không)? Theo tôi hiểu autoboxing, Integer a = 42; a == 1 && a == 2 && a == 3nên đóng hộp tất cả các số nguyên. Hoặc điều này unbox a để so sánh?
CAD97

@ CAD97: Integer == intdường như dẫn đến việc bỏ hộp. Nhưng sử dụng Integer#equals(int)lực lượng autoboxing, vì vậy nó hoạt động. Cảm ơn các bình luận!
Eric Duminil

@StephanBijzitter: Hãy giải thích. Theo như tôi biết, chỉ có Numberstrong JS, về cơ bản giống như doubles. Chúng có thể trông giống như số nguyên và bạn có thể sử dụng chúng như số nguyên, nhưng chúng vẫn không phải là số nguyên. Tôi không nghĩ n == n + 1có thể đúng với các số nguyên trong Java / Python / C / Ruby / ...
Eric Duminil

80

Đây là một phiên bản ngược của @ Jeff câu trả lời * nơi một nhân vật ẩn (U + 115F, U + 1160 hoặc U + 3164) được sử dụng để tạo ra các biến mà nhìn như 1, 23.

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

* Câu trả lời đó có thể được đơn giản hóa bằng cách sử dụng công cụ không tham gia chiều rộng bằng không (U + 200C) và công cụ tham gia chiều rộng bằng không (U + 200D). Cả hai ký tự này đều được phép bên trong các định danh nhưng không phải ở đầu:

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

Các thủ thuật khác có thể sử dụng cùng một ý tưởng, ví dụ: bằng cách sử dụng các bộ chọn biến thể Unicode để tạo các biến trông giống hệt nhau ( a︀ = 1; a︁ = 2; a︀ == 1 && a︁ == 2; // true).


75

Quy tắc số một của các cuộc phỏng vấn; không bao giờ nói không thể

Không cần phải lừa nhân vật ẩn.

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
Ôi. __defineGetter__thực sự không phải là một phần của ngôn ngữ js, chỉ là một phiên bản xấu xí của defineProperty. typeofkhông phải là một chức năng và điều này không iđược công bố là khủng khiếp. Vẫn có vẻ đáng giá 40 upvote: /
Jonas Wilms

6
@JasasW. 41 upvote :-) Tôi biết rằng __defineGetter__không được chấp nhận cho mỗi developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/, nhưng nó thực thi rõ ràng trong FireFox v 57.0.4 của tôi vì vậy tôi đã chọn hiển thị điều này thay vì defineProperty()bởi vì mã kế thừa là có thật và không thể bỏ qua. Bất kể sự xấu xí, tuyên bố itheo cách tôi đã làm là một hành vi nổi tiếng / tài liệu. Có lẽ tôi đang ở trong tâm trạng PCG ¯ \ _ (ツ) _ /
MonkeyZeus

68

Thành thật mà nói, liệu có cách nào để đánh giá đúng hay không (và như những người khác đã chỉ ra, có nhiều cách), câu trả lời tôi đang tìm kiếm, nói như một người đã thực hiện hàng trăm cuộc phỏng vấn, sẽ là một cái gì đó dọc theo dòng:

"Chà, có lẽ là có trong một số tình huống kỳ lạ không rõ ràng đối với tôi ... nhưng nếu tôi gặp phải điều này trong mã thực thì tôi sẽ sử dụng các kỹ thuật sửa lỗi phổ biến để tìm ra cách thức và lý do tại sao nó đang làm những gì nó đang làm và sau đó ngay lập tức cấu trúc lại mã để tránh tình huống đó ... nhưng quan trọng hơn: tôi hoàn toàn KHÔNG BAO GIỜ viết mã đó ngay từ đầu bởi vì đó là định nghĩa về mã phức tạp và tôi cố gắng không bao giờ viết mã phức tạp ".

Tôi đoán một số người phỏng vấn sẽ xúc phạm khi có câu hỏi rõ ràng là một câu hỏi rất khó, nhưng tôi không bận tâm đến những nhà phát triển có ý kiến, đặc biệt là khi họ có thể sao lưu nó với suy nghĩ hợp lý và có thể phù hợp với câu hỏi của tôi một tuyên bố có ý nghĩa về bản thân họ.


13
Câu hỏi (hoặc tất cả các câu hỏi phỏng vấn) có lẽ là để kiểm tra các ứng viên sẵn sàng suy nghĩ về một vấn đề, đặc biệt là những vấn đề "rõ ràng rõ ràng", như câu hỏi này. Một số người từ chối suy nghĩ bởi vì họ tin rằng họ "biết" câu trả lời không phải là một thuê tốt.
Shammoo

5
@Don nở Không, tôi sẽ không phạt họ nếu họ trả lời một cách trung thực và đặc biệt là nếu họ trả lời đúng như những người khác đã trình bày ... nhưng sau đó tôi sẽ hỏi tiếp theo để thử và thăm dò xem họ có nghĩ như vậy không một cách tốt để viết mã hay không. Hiểu biết và có thể đưa ra câu trả lời "chính xác" chỉ là một phần của việc trở thành một nhà phát triển giỏi. Điều quan trọng hơn nhiều đối với một nhà phát triển "chuyên nghiệp" là viết mã dễ hiểu và có thể duy trì được, thường là bởi các nhà phát triển kém năng lực hơn. Các nhà phát triển quá thông minh cũng khá tệ như những người không có khả năng IME.
Frank W. Zammetti

16
Điều này không trả lời câu hỏi.
TylerH

6
Điều đáng buồn về câu trả lời này là một người dùng 1rep đã trả lời rằng ngày hôm qua và có 2 lượt tải xuống khiến anh ta phải xóa câu hỏi này.
Jonas Wilms

8
@JohnColeman câu hỏi hỏi làm thế nào mã có thể đánh giá là đúng. Nó không hỏi lý do người phỏng vấn đề xuất câu hỏi ngay từ đầu. Câu trả lời này thậm chí không cố gắng giải quyết câu hỏi đang được hỏi, mà thay vào đó tập trung hoàn toàn vào phiên bản "tôi sẽ làm gì" trong nỗ lực đoán mục đích của người phỏng vấn. Nếu đó là câu hỏi được hỏi, nó sẽ quá rộng. Do đó, câu trả lời này không thuộc về nơi này hoặc bất cứ nơi nào trên trang web.
TylerH

43

Nếu bạn từng nhận được một câu hỏi phỏng vấn như vậy (hoặc nhận thấy một số hành vi bất ngờ tương tự trong mã của bạn), hãy nghĩ về loại điều nào có thể gây ra hành vi trông không thể ngay từ cái nhìn đầu tiên:

  1. Mã hóa : Trong trường hợp này, biến bạn đang xem không phải là biến bạn nghĩ. Điều này có thể xảy ra nếu bạn cố tình làm rối với Unicode bằng cách sử dụng các ký tự đồng nhất hoặc ký tự khoảng trắng để làm cho tên của biến giống như một biến khác, nhưng các vấn đề mã hóa cũng có thể được đưa ra một cách tình cờ, ví dụ như khi sao chép và dán mã từ Web có chứa mã Unicode bất ngờ điểm (ví dụ: vì hệ thống quản lý nội dung đã thực hiện một số "định dạng tự động", chẳng hạn như thay thế flbằng Unicode 'LATIN SMALL LIGATURE FL' (U + FB02)).

  2. Điều kiện cuộc đua : Điều kiện cuộc đua có thể xảy ra, tức là tình huống mã không được thực thi theo trình tự mà nhà phát triển mong đợi. Điều kiện cuộc đua thường xảy ra trong mã đa luồng, nhưng nhiều luồng không phải là yêu cầu đối với điều kiện cuộc đua là có thể - sự không đồng bộ là đủ (và không bị nhầm lẫn, không đồng bộ không có nghĩa là nhiều luồng được sử dụng dưới mui xe ).

    Lưu ý rằng do đó JavaScript cũng không thoát khỏi các điều kiện chủng tộc chỉ vì nó là luồng đơn. Xem ở đây để biết một ví dụ đơn luồng - nhưng không đồng bộ - ví dụ. Tuy nhiên, trong bối cảnh của một tuyên bố, điều kiện cuộc đua sẽ khá khó khăn trong JavaScript.

    JavaScript với nhân viên web hơi khác một chút, vì bạn có thể có nhiều luồng. @mehulmpt đã cho chúng ta thấy một bằng chứng tuyệt vời về khái niệm sử dụng nhân viên web .

  3. Tác dụng phụ : Một tác dụng phụ của hoạt động so sánh bình đẳng (không cần phải rõ ràng như trong các ví dụ ở đây, thường là các tác dụng phụ rất tinh tế).

Các loại vấn đề này có thể xuất hiện trong nhiều ngôn ngữ lập trình, không chỉ JavaScript, vì vậy chúng tôi không thấy một trong các WTF cổ điển ở đây 1 .

Tất nhiên, câu hỏi phỏng vấn và các mẫu ở đây đều trông rất giả tạo. Nhưng họ là một lời nhắc tốt rằng:

  • Các tác dụng phụ có thể trở nên thực sự khó chịu và một chương trình được thiết kế tốt sẽ không có tác dụng phụ không mong muốn.
  • Đa luồng và trạng thái đột biến có thể có vấn đề.
  • Không thực hiện mã hóa ký tự và xử lý chuỗi đúng có thể dẫn đến các lỗi khó chịu.

1 Ví dụ: bạn có thể tìm thấy một ví dụ bằng ngôn ngữ lập trình hoàn toàn khác (C #) thể hiện hiệu ứng phụ (một điều hiển nhiên) ở đây .


1
Sau đó, câu hỏi trở nên quá rộng. Các ngôn ngữ khác nhau có thể thực hiện điều này với mức độ dễ dàng khác nhau. Câu hỏi đã thu được rất nhiều lực kéo bởi vì đây là một câu hỏi và trả lời cụ thể về JS, nhưng đó chỉ là 2c của tôi.
cs95

1
nguyên nhân là C # và javascript khác nhau nên câu trả lời này không hợp pháp.
Edwin

3
@Edwin: Các nguyên nhân hoàn toàn giống nhau: Unicode biến đổi với glyphs hoặc ký tự khoảng trắng trông giống nhau, điều kiện chủng tộc hoặc tác dụng phụ của hoạt động so sánh (ví dụ sau được hiển thị trong ví dụ của tôi).
Dirk Vollmar

2
@ cᴏʟᴅsᴘᴇᴇᴅ: Đôi khi nhìn mọi thứ từ góc độ rộng hơn giúp thấy vấn đề thực tế.
Dirk Vollmar

3
Tôi muốn câu trả lời này có thể được gắn thẻ cho câu hỏi này theo một cách nào đó "meta". Sau khi đọc tất cả các câu trả lời ở trên, tôi cảm thấy như JS có quá nhiều lỗ hổng, nhưng bạn chỉ tóm tắt tất cả các câu trả lời trong một lần. Và bạn đã làm nó theo cách biến điều này thành một câu hỏi phỏng vấn xuất sắc (nếu thẻ cụ thể theo ngôn ngữ bị xóa) theo ý kiến ​​của tôi. Bravo!
KCE

41

Đây là một biến thể khác, sử dụng một mảng để bật ra bất kỳ giá trị nào bạn muốn.

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

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


31

Được rồi, một hack với máy phát điện:

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


Bạn nói hack, nhưng tôi khá chắc chắn đây là trường hợp sử dụng máy phát điện ... :) (tốt, ngoại trừ việc điều này phụ thuộc vào thisviệc trở thành đối tượng cửa sổ)
Cody

29

Sử dụng 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);

Các proxy về cơ bản giả vờ là một đối tượng đích (tham số đầu tiên), nhưng chặn các hoạt động trên đối tượng đích (trong trường hợp này là thao tác "lấy thuộc tính") để có cơ hội thực hiện một việc khác ngoài hành vi đối tượng mặc định. Trong trường hợp này, hành động "lấy tài sản" được gọi akhi ==ép buộc loại của nó để so sánh nó với từng số. Điều này xảy ra:

  1. Chúng tôi tạo một đối tượng mục tiêu { i: 0 }, trong đó itài sản là đối tác của chúng tôi
  2. Chúng tôi tạo một Proxy cho đối tượng đích và gán nó cho a
  3. Đối với mỗi a ==so sánh, aloại của bị ép buộc thành một giá trị nguyên thủy
  4. Kiểu ép buộc này dẫn đến việc gọi a[Symbol.toPrimitive]()nội bộ
  5. Proxy chặn a[Symbol.toPrimitive]chức năng sử dụng "trình xử lý get"
  6. "Trình xử lý" của Proxy kiểm tra xem thuộc tính đang nhận được Symbol.toPrimitive, trong trường hợp đó, nó tăng lên và sau đó trả về bộ đếm từ đối tượng đích : ++target.i. Nếu một thuộc tính khác đang được truy xuất, chúng ta sẽ quay lại trả về giá trị thuộc tính mặc định,target[name]

Vì thế:

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

Như với hầu hết các câu trả lời khác, điều này chỉ hoạt động với kiểm tra đẳng thức lỏng lẻo ( ==), bởi vì kiểm tra đẳng thức nghiêm ngặt ( ===) không thực hiện ép buộc kiểu mà Proxy có thể chặn.


2
Tuy nhiên, không có điểm nào trong việc sử dụng proxy cho việc này - việc xác định Symbol.toPrimitivetheo cùng một cách trên một đối tượng cũng sẽ hoạt động tốt.
Ry-

27

Trên thực tế, câu trả lời cho phần đầu tiên của câu hỏi là "Có" trong mọi ngôn ngữ lập trình. Ví dụ: đây là trong trường hợp của 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
Tôi không nghĩ rằng nó có thể trong mọi ngôn ngữ lập trình. Không phải tất cả các ngôn ngữ đều có tiền xử lý, ví dụ. Đối với vấn đề đó, không phải tất cả các ngôn ngữ sử dụng &&cho logic "và".
Keith Thompson

3
Tôi đã tìm thấy một cách hoạt động cả trong PythonC ++ , sử dụng quá tải toán tử.
Vịt Donald

7
Và bạn có thể làm điều đó trong Java bằng cách sử dụng sự phản chiếu và làm rối bộ đệm nguyên.
CAD97

7
Không thể làm điều đó bằng các ngôn ngữ không hỗ trợ đột biến ở điểm đó, ví dụ: không có gì có thể so sánh được ở haskell
Jason Carr

4
Câu hỏi là hỏi về JavaScript, không phải C ++.
Tất cả công nhân đều cần thiết vào

26

Giống nhau, nhưng khác nhau, nhưng vẫn giống nhau (có thể được "kiểm tra" nhiều lần):

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

Ý tưởng của tôi bắt đầu từ cách phương trình Số đối tượng hoạt động.


4
Hoạt động lần thứ hai quá!
Salman A

25

Câu trả lời ECMAScript 6 sử dụng các Biểu tượng:

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

Do ==sử dụng, JavaScript có nghĩa vụ phải ép buộc avào một cái gì đó gần với toán hạng thứ hai ( 1, 2, 3trong trường hợp này). Nhưng trước khi JavaScript cố gắng tự mình ép buộc, nó cố gắng gọi Symbol.toPrimitive. Nếu bạn cung cấp Symbol.toPrimitiveJavaScript sẽ sử dụng giá trị mà hàm của bạn trả về. Nếu không, JavaScript sẽ gọi valueOf.


24

Tôi nghĩ rằng đây là mã tối thiểu để thực hiện nó:

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

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

Tạo một đối tượng giả với một tùy chỉnh valueOflàm tăng một biến toàn cục itrên mỗi cuộc gọi. 23 ký tự!


14

Cái này sử dụng phần xác định với hiệu ứng phụ đẹp mắt gây ra biến toàn cục!

var _a = 1

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

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


8
bạn có thể sử dụng một bao đóng a: get: (a => () => ++a)(0),không cần thiết toàn cầu.
Nina Scholz

13
@NinaScholz chắc chắn, nhưng chúng ta đang nói về những thực hành xấu ở đây - hãy để tôi có cái này: D
Ben Aubin

1

Bằng cách ghi đè valueOftrong một khai báo lớp, nó có thể được thực hiện:

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

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

const a = new Thing();

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

Điều gì xảy ra là valueOfđược gọi trong mỗi toán tử so sánh. Ở lần đầu tiên, asẽ bằng nhau 1, vào lần thứ hai, asẽ bằng nhau 2, và cứ thế, bởi vì mỗi lần valueOfđược gọi, giá trị của ađược tăng lên.

Do đó, console.log sẽ kích hoạt và xuất ra (trong mọi thiết bị đầu cuối của tôi) Thing: { value: 4}, cho biết điều kiện là đúng.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.