Lưu ý của người điều hành: Vui lòng không muốn chỉnh sửa mã hoặc xóa thông báo này. Mẫu khoảng trắng có thể là một phần của câu hỏi và do đó không nên giả mạo 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ờ điều đó (a== 1 && a ==2 && a==3)
có thể đánh giá true
trong JavaScript không?
Đâ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ò.
Nếu bạn tận dụng được cách thức ==
hoạt động , bạn có thể chỉ cần tạo một đối tượng với một hàm toString
(hoặc valueOf
) tùy chỉnh 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 điều này hoạt động là do việc sử dụng toán tử bình đẳng lỏng lẻo. Khi sử dụng đẳng thức lỏng, nếu một trong các toán hạng có kiểu khác với toán hạng khác, công cụ sẽ cố gắng chuyển đổi từ này sang kiểu kia. 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 valueOf
nếu nó có thể gọi được, và thất bại, nó sẽ gọi toString
. Tôi sử dụng toString
trong trường hợp này đơn giản vì đó là những gì tôi nghĩ đến, valueOf
sẽ có ý nghĩa hơn. Thay vào đó, nếu tôi trả về một chuỗi từ đó toString
, thì công cụ sẽ cố chuyển đổi chuỗi thành một số cho chúng ta cùng một kết quả cuối cùng, mặc dù với một đường dẫn dài hơn một chút.
Tôi không thể cưỡng lại - các câu trả lời khác chắc chắn là đúng, nhưng bạn thực sự không thể vượt 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 if
câu lệnh (mà tôi đã sao chép từ câu hỏi của bạn). Đó là Hangul nửa độ rộng (đó là tiếng Hàn đối với những người không quen thuộc) là một ký tự dấu cách Unicode không được tập lệnh ECMA giải thích là một ký tự khoảng trắng - điều này có nghĩa là nó là một ký tự hợp lệ cho một số nhận dạng. Do đó, có ba biến hoàn toàn khác nhau, một với Hangul sau dấu a, một với nó trước và biến cuối cùng chỉ với a. Thay thế khoảng trắng bằng _
để dễ đọc, mã tương tự sẽ giống như sau:
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 thực 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 đưa vào 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.
Chỉnh sửa: Tôi nhận thấy rằng (mặc dù không được phép bắt đầu một biến), các ký tự nối 0-width và các ký tự không phải nối 0-width cũng được phép trong tên biến - xem JavaScript xáo trộn với các ký tự không-width - ưu và nhược điểm ? .
Điều này sẽ giố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!")
}
Đ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 with
câu lệnh để cho phép a
đánh giá đến 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.");
}
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);
Điều này hoạt động bởi vì ==
gọi toString
mà gọi .join
cho Mảng.
Một giải pháp khác, sử dụng Symbol.toPrimitive
ES6 tương đương với toString/valueOf
:
let i = 0;
let a = { [Symbol.toPrimitive]: () => ++i };
console.log(a == 1 && a == 2 && a == 3);
Nếu nó được hỏi là có thể (KHÔNG PHẢI), nó có thể yêu cầu "a" trả về một số ngẫu nhiên. Sẽ đúng nếu nó tạo ra 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;
}
}
}
Khi bạn không thể làm bất cứ điều gì mà không có biểu thức chính quy:
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 nhờ valueOf
phương thức tùy chỉnh được gọi khi Đối tượng được so sánh với nguyên thủy (chẳng hạn như Số). Thủ thuật chính là a.valueOf
trả về giá trị mới mọi lúc vì nó đang gọi exec
biểu thức chính quy với g
cờ, điều này gây ra việc cập nhật lastIndex
biểu thức chính quy đó mỗi khi tìm thấy đối sánh. Vì vậy, lần đầu tiên this.r.lastIndex == 0
, nó khớp 1
và cập nhật lastIndex
: this.r.lastIndex == 1
, vì vậy lần sau regex sẽ khớp 2
, v.v.
Nó có thể được thực hiện bằng cách sử dụng những điều sau đây trong phạm vi toàn cầu. Để nodejs
sử dụng global
thay vì window
trong 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 ngầm định đượ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.
Điều này có thể xảy ra trong trường hợp biến a
được truy cập bởi 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 a
chỉ trong thời gian như vậy điều kiện a==1
, a==2
và a==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 web worker và SharedArrayBuffer trong JavaScript.
Đây là cách triển khai 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:
Lần thử thứ hai:
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 quá lâu trên hệ thống của bạn. Chỉ thử a == 1 && a == 2
và thay đổi Math.random()*3
thành Math.random()*2
. Thêm nhiều hơn và nhiều hơn vào danh sách làm giảm cơ hội đánh.
Điều này cũng có thể thực hiện được bằng cách 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 bộ đế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.");
}
})();
Ngoài ra, bạn có thể sử dụng một lớp cho nó và một thể hiện để 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ẽ giố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!');
}
Tôi không thấy câu trả lời này đã được đăng, vì vậy tôi cũng sẽ ném 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 a = 2;
var а = 3;
if(a == 1 && a == 2 && а == 3) {
console.log("Why hello there!")
}
Bạn có thể nhận thấy một chút khác biệt với cái thứ hai, nhưng cái thứ nhất và thứ ba giống hệt nhau bằng mắt thường. Cả 3 đều là các ký tự riêng biệt:
a
- Chữ thường
a
Latinh A
а
- Chữ thường Latinh có Chiều rộng Đầy đủ A - Chữ thường chữ Kirin 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, rất khó để có được ba chiếc mà 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. A, Α, А, và Ꭺ sẽ làm việc tốt hơn (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 không giúp được gì với đoạn mã trên).
Có cả một lớp các cuộc tấn công Homoglyph ở đó, phổ biến nhất là trong các tên miền giả mạo (ví dụ: wikipediа.org
(Cyrillic) so với wikipedia.org
(Latin)), nhưng nó cũng có thể hiển thị trong mã; thường được gọi là bị ám chỉ (như đã đề cập trong một nhận xét, các câu hỏi [ám chỉ] hiện không chủ đề trên PPCG , nhưng từng là một loại thử thách mà những thứ này sẽ hiển thị). Tôi đã sử dụng trang web này để tìm các chữ đồng nhất được sử dụng cho câu trả lời này.
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 (cảm ơn @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ĩ chỉ cần nói Có, có thể với ai đó đã nói với bạn: Không 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 tương tự như tên của nó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à một giảif
, nhưng nó hiệu quả cho bạn trong trường hợp này!
Ngoài ra, tôi đã viết một phiên bản C # ( với kỹ thuật gia 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!😎");
}
}
Trong JavaScript, không có số nguyên mà chỉ có Number
s, được triển khai dưới dạng số dấu phẩy động có độ chính xác kép.
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, nó không chính xác những gì người phỏng vấn yêu cầu (nó không hoạt động với a=0
), nhưng nó không liên quan đến bất kỳ thủ thuật nào với các hàm ẩn hoặc quá tải toán tử.
Để tham khảo, có a==1 && a==2 && a==3
các giải pháp bằng Ruby và Python. Với một chút sửa đổi, nó cũng có thể thực hiện được trong Java.
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 ngày càng tăng a
:
def a
@a ||= 0
@a += 1
end
if a == 1 && a == 2 && a == 3
puts "Don't do this!"
end
class A:
def __eq__(self, who_cares):
return True
a = A()
if a == 1 and a == 2 and a == 3:
print("Don't do that!")
Có thể sửa đổi Integer
bộ đệ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.");
}
}
}
Đâ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
, 2
và 3
.
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 bộ nối không có độ rộng bằng không (U + 200C) và bộ nối có độ rộng bằng 0 (U + 200D). Cả hai ký tự này đều được phép bên trong số nhận dạng nhưng không được phép ở đầ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 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
).
Quy tắc số một khi phỏng vấn; không bao giờ nói không thể.
Không cần thủ thuật ẩn ký tự.
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?' );
}
Thành thật mà nói, cho dù có cách nào để nó đánh giá là đúng hay không (và như những người khác đã chỉ ra, có nhiều cách), câu trả lời mà tôi đang tìm kiếm, nói với tư cách là 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 của:
"Chà, có thể có trong một số tình huống kỳ lạ mà tôi không rõ ràng ngay lập tức ... 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 gỡ lỗi phổ biến để tìm ra cách thức và lý do tại sao nó hoạt động như thế nào 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 tuyệt đối KHÔNG BAO GIỜ viết mã đó ngay từ đầu vì đó là định nghĩa của 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 rằng một số người phỏng vấn sẽ cảm thấy khó chịu khi có những gì rõ ràng là một câu hỏi rất khó được gọi ra, nhưng tôi không ngại 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ể hiểu câu hỏi của tôi thành một câu nói ý nghĩa về bản thân họ.
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ề những thứ có thể gây ra một hành vi thoạt nhìn là không thể:
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 gây 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 một biến trông giống một biến khác, nhưng các vấn đề mã hóa cũng có thể vô tình được đưa ra, ví dụ: khi sao chép và dán mã từ Web có chứa mã Unicode không mong muốn điểm (ví dụ: vì hệ thống quản lý nội dung đã thực hiện một số "tự động định dạng", chẳng hạn như thay thế fl
bằng Unicode 'LATIN SMALL LIGATURE FL' (U + FB02)).
Điều kiện cuộc đua : Tình trạng cuộc đua có thể xảy ra, tức là một tình huống trong đó mã không 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ều kiện đua có thể thực hiện được - tính không đồng bộ là đủ (và đừng 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à một luồng. Xem tại đây để biết ví dụ đơn giản về một luồng - nhưng không đồng bộ -. Tuy nhiên, trong ngữ cảnh của một câu lệnh, điều kiện chủng tộc sẽ khó đạt được trong JavaScript.
JavaScript với web worker 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 .
Tác dụng phụ : Một tác dụng phụ của phép toán so sánh bình đẳng (không nhất thiết phải rõ ràng như trong các ví dụ ở đây, các tác dụng phụ thường rất nhỏ).
Những vấn đề kiểu 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 JavaScript 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 chúng là một lời nhắc nhở tốt rằng:
1 Ví dụ, bạn có thể tìm thấy một ví dụ bằng một ngôn ngữ lập trình hoàn toàn khác (C #) thể hiện một tác dụng phụ (một hiệu ứng hiển nhiên) tại đây .
Đâ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');
}
Được rồi, một cuộc tấn công khác 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!');
}
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);
Về cơ bản proxy 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à hoạt động "lấy thuộc tính") để có cơ hội thực hiện điều gì đó khác với hành vi của đối tượng mặc định. Trong trường hợp này, hành động "lấy thuộc tính" được gọi a
khi ==
cưỡng chế kiểu của nó để so sánh nó với từng số. Điều này xảy ra:
{ i: 0 }
, nơi thuộc i
tính là bộ đếm của chúng tôia
a ==
so sánh, a
kiểu của được ép buộc thành một giá trị nguyên thủya[Symbol.toPrimitive]()
nội bộa[Symbol.toPrimitive]
chức năng bằng cách sử dụng "get handler"Symbol.toPrimitive
, trong trường hợp này nó increments và sau đó quay lại đếm từ đối tượng mục tiêu: ++target.i
. Nếu một thuộc tính khác đang được truy xuất, chúng tôi chỉ 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 bình đẳng lỏng lẻo ( ==
), bởi vì kiểm tra bình đẳng nghiêm ngặt ( ===
) không thực hiện cưỡng chế loại mà Proxy có thể chặn.
Thực ra 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à 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;
}
Giống nhau, nhưng khác nhau, nhưng vẫn giống nhau (có thể "thử nghiệm" 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 thức hoạt động của phương trình kiểu đối tượng Số.
Một 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 a
vào một cái gì đó gần với toán hạng thứ hai ( 1
, 2
, 3
trong trường hợp này). Nhưng trước khi JavaScript cố gắng tự tìm cách ép buộc, nó sẽ cố gắng gọi Symbol.toPrimitive
. Nếu bạn cung cấp Symbol.toPrimitive
JavaScript sẽ sử dụng giá trị mà hàm của bạn trả về. Nếu không, JavaScript sẽ gọi valueOf
.
Tôi nghĩ đây là mã tối thiểu để triển khai 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 valueOf
làm tăng biến toàn cục i
trên mỗi lần gọi. 23 ký tự!
Cái này sử dụng defineProperty với một hiệu ứng phụ 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)
Bằng cách ghi đè valueOf
trong 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 được valueOf
gọi trong mỗi toán tử so sánh. Trên lần đầu tiên, a
sẽ bằng nhau 1
, trên lần thứ hai, a
sẽ bằng nhau 2
, v.v., 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 thiết bị đầu cuối của tôi) Thing: { value: 4}
, cho biết điều kiện là đúng.
Cate Blanchett đã bất chấp những lời khuyên hẹn hò điển hình khi cô gặp chồng mình.
Michael Sheen là một diễn viên phi lợi nhuận nhưng chính xác thì điều đó có nghĩa là gì?
Ngôi sao của Hallmark Colin Egglesfield chia sẻ về những cuộc gặp gỡ với người hâm mộ ly kỳ tại RomaDrama Live! cộng với chương trình INSPIRE của anh ấy tại đại hội.
Bạn sẽ phải phủi sạch đầu đĩa Blu-ray hoặc DVD để xem tại sao Northern Exposure trở thành một trong những chương trình nổi tiếng nhất của thập niên 90.
The world is a huge place, yet some GeoGuessr players know locations in mere seconds. Are you one of GeoGuessr's gifted elite? Take our quiz to find out!
Bạn biết đấy, hai sản phẩm này là nguồn điện để làm sạch, riêng chúng. Nhưng cùng với nhau, chúng có một loạt công dụng hoàn toàn khác.
Thủy điện rất cần thiết cho lưới điện của Hoa Kỳ, nhưng nó chỉ tạo ra năng lượng khi có nước di chuyển. Bao nhiêu nhà máy thủy điện có thể gặp nguy hiểm khi các hồ và sông cạn kiệt?
Tóc tỉa từ các tiệm và các khoản quyên góp cá nhân có thể được tái sử dụng như những tấm thảm thấm dầu và giúp bảo vệ môi trường.
Sau khi Sarah Palin tán thành Donald Trump vào đầu tuần này, gần như không thể tránh khỏi việc Tina Fey sẽ trở lại Saturday Night Live để thăm lại ấn tượng Palin cổ điển của cô. Và Fey chắc chắn đã không làm thất vọng, cô ấy đã đưa ra một lời khen ngợi không hề nhẹ về bài phát biểu chứng thực Iowa quanh co và khó hiểu của Palin trong khi Trump của Darrell Hammond đưa ra bình luận xuyên suốt.
Brittney Griner (r.) Ngay từ đầu, thân phận của Brittney Griner đã là tình huống con tin Mỹ độc nhất trong lịch sử hiện đại.
Chúng ta có thể thấy nhiều hơn nữa về một Julio Jones khỏe mạnh trong khu vực cuối năm nay. John Parker Wilson, Greg McElroy, A.
Đối với đội tuyển Anh, không có kẻ thủ ác nào lớn hơn Hầu hết các cổ động viên Anh, nếu không muốn nói là tất cả, hẳn sẽ phải gật gù khi tiếng còi mãn cuộc của trận bán kết lượt về W Euro 2022 vang lên. Bởi vì nó báo hiệu rằng Đức sẽ chờ đợi ở Wembley trong trận chung kết với Anh và là điều duy nhất giữa Anh và chiếc cúp lớn đầu tiên của đội tuyển nữ.
Nicky Hilton Rothschild's luggage got lost, but luckily she has an incredible closet to shop: Sister Paris Hilton's!
Kate Middleton dành một ngày bên bờ nước ở London, cùng với Jennifer Lopez, Julianne Hough và hơn thế nữa. Từ Hollywood đến New York và mọi nơi ở giữa, hãy xem các ngôi sao yêu thích của bạn đang làm gì!
Các nhà điều tra đang xem xét liệu nhóm và nghi phạm có biết nhau trước vụ tấn công hay không
Vụ kiện, nêu tên một số học khu, lập luận rằng dự luật "Không nói đồng tính" được ban hành gần đây của Florida "có hiệu quả im lặng và xóa bỏ học sinh và gia đình LGBTQ +"
Cuối hè đầu thu là mùa hoài niệm. Những chiếc đèn đường chiếu ánh sáng của chúng qua những con đường đẫm mưa, và những chiếc lá dưới chân - màu đỏ cam tắt trong bóng chạng vạng - là lời nhắc nhở về những ngày đã qua.
Vào năm 2021, tôi khuyến khích bạn suy nghĩ lại mọi thứ bạn biết về khách hàng mà bạn phục vụ và những câu chuyện bạn kể cho họ. Lùi lại.
Vào ngày sinh nhật thứ 9 của Felix The Cat, tôi nhớ về một trong những mất mát lớn nhất trong cuộc đời trưởng thành của tôi - Sophie của tôi vào năm 2013. Tôi đã viết bài luận này và chia sẻ nó trên nền tảng này một thời gian ngắn vào năm 2013.
Tôi ghét từ "tàu đắm". Mọi người cảm thấy thoải mái trong la bàn đạo đức của riêng mình, và khi làm như vậy, họ thấy mình vượt qua sự phán xét.