Tại sao {} + {} không còn NaN trong bảng điều khiển Chrome?


144

Hôm nay tôi nhận thấy rằng Chrome 49 không còn xuất ra NaNkhi bạn nhập {}+{}vào bảng điều khiển. Thay vào đó, nó đưa ra chuỗi [object Object][object Object].

Tại sao lại thế này? Ngôn ngữ có thay đổi không?


13
có vẻ như chrome bây giờ coi hoạt động này là một chuỗi concat chứ không phải là bổ sung. TẠI SAO đó là, tôi không biết, đó là lý do tại sao đây là một nhận xét không phải là một câu trả lời :) hãy thử var e = {}; e.toString()và bạn sẽ thấy ý của tôi
user428517

19
"Ngôn ngữ có thay đổi không?" Số
Felix Kling

6
@FelixKling sẽ thay đổi ngôn ngữ? ...Không. : c
con mèo

18
Có lẽ WATMAN có cái gì đó để làm với nó?
còi xương

1
@rickster đó là cách tôi tìm thấy nó. Tôi đã tái tạo nó để trình bày.
Filip Haglund

Câu trả lời:


152

Chrome devtools hiện tự động bao bọc mọi thứ bắt đầu {và kết thúc bằng }một cặp dấu ngoặc đơn ( xem mã ), để buộc đánh giá của nó là một biểu thức. Bằng cách đó, {}tạo ra một đối tượng trống bây giờ. Bạn có thể thấy điều này nếu bạn quay lại lịch sử ( ), dòng trước đó sẽ được chứa trong đó (…).

Tại sao? Tôi không biết, nhưng tôi có thể đoán nó làm giảm sự nhầm lẫn cho những người mới không biết về khối chữ-đối tượng-nghĩa đen và nó cũng hữu ích hơn nếu bạn chỉ muốn đánh giá một biểu thức.

Và trên thực tế, đó là lý do, như đã thảo luận trong lỗi 499864 . Tinh khiết tiện lợi. Và bởi vì nút REPL cũng có nó ( xem mã ).


182
Chrome ngu ngốc, {a:1}),({b:2}nên ném một lỗi, không tạo ra một đối tượng.
Oriol

29
Đó là những gì xảy ra khi bạn phân tích các cấu trúc lồng nhau sâu tùy ý với regex stackoverflow.com/questions/1732348/
Kẻ

4
Tôi không biết tại sao, nhưng bằng cách nào đó khi tôi thấy tin nhắn của mình ở đó tôi cảm thấy "nổi tiếng" mặc dù trang đó cũng công khai như trang này: Vấn đề StackOverflow kỳ lạ. Đây là câu trả lời cũ hơn của tôi về vấn đề stackoverflow.com/questions/17268468/
Kẻ

3
Tôi không thích cách triển khai hiện tại và có kế hoạch sửa nó. bug.chromium.org/p/chromium/issues/detail?id=499864#c17
Zirak

1
@Zirak Chúc may mắn sửa rác đó, IMO nó nên được sao lưu càng sớm càng tốt. Nhưng nếu bạn muốn cải thiện nó, hãy xem xét thêm một dòng mới trước khi chèn )trong trường hợp nó trong một bình luận, ví dụ như {a:3} // :-}vẫn có thể tạo ra một đối tượng.
Oriol

44

Nếu bạn nhấn mũi tên lên sau khi kiểm tra điều này, bạn sẽ nhận thấy rằng thay vì {} + {}nó hiển thị ({} + {}), kết quả sẽ dẫn đến "[object Object][object Object]".

So sánh, trong Firefox, {} + {}vẫn hiển thị NaN, nhưng nếu bạn làm ({} + {})thì nó cũng hiển thị "[object Object][object Object]".

Vì vậy, có vẻ như Chrome đang tự động thêm dấu ngoặc đơn xung quanh khi thấy hoạt động này.


22
Câu trả lời này là chính xác. nhưng wow, anh bạn, tôi không chắc là tôi thích cái chrome đó. xấu google.
dùng428517

1
@sgroves Tôi muốn biết liệu điều này có giống với Canary không và liệu nó có được thực hiện trên mục đích hay thực sự là một lỗi.
J. Titus

8
{} + {}khi không được "khử trùng" thành ({} + {})được coi là + {}{}được phân tích cú pháp dưới dạng một khối trống.
Gregory Nisbet

7
Tại sao nó sẽ trả lại NaN ngay từ đầu?
0x499602D2

25
@ 0x499602D2: Bởi vì trừ khi bạn làm Parens (hoặc nguyên nhân phân tích cú pháp để thay đổi thành mong đợi một biểu thức chứ không phải là tuyên bố), ban đầu {}chỉ là một khối mã rỗng và được bỏ qua, để lại cho chúng ta +{}, mà là một unary +và một đối tượng rỗng người khởi tạo. +sẽ ép buộc đối số của nó thành số, liên quan đến việc chuyển đổi đối tượng thành nguyên thủy (kết quả là toStringtrong trường hợp này, dẫn đến "[object Object]"), và vì vậy chúng ta nhận được +"[object Object]"đó là NaN"[object Object]"không thể chuyển đổi thành số hợp lệ.
TJ Crowder

4

Kể từ Chrome 54 liên quan đến bảng điều khiển:

-"Tôi đã chuyển đổi khối đó thành Đối tượng cho bạn" -Clippy Thật không may, tôi đã thêm trích dẫn Clippy mình. Bảng điều khiển không cung cấp thông tin về những gì nó đã làm cho bạn.

Các quy tắc mới cực kỳ đơn giản giúp chúng tôi tránh được rắc rối khi phải gõ 2 từ khóa khó khăn này o=hoặc 0,trước khi dán Object Literals vào bảng điều khiển:

  • Nếu bạn có mã bắt đầu bằng: khoảng trắng tùy chọn, (không cho phép nhận xét) theo sau là a {;
  • và mã đó có thể được hiểu là một đối tượng;
  • và đối tượng đó được theo sau bởi không có mã nào khác, trừ khi:
  • mã sau đối tượng đầu tiên là toán tử nhị phân,
  • sau đó có thể có nhiều thao tác như bạn muốn bao gồm các nhóm
  • với điều kiện toán tử cuối cùng có một đối tượng bằng chữ ở vị trí bên tay phải;
  • và đối tượng cuối cùng đó đã không được nhóm trong parens
  • và mã đó không được chấm dứt bằng dấu chấm phẩy
  • và không có bình luận nào theo mã (bình luận nội bộ được cho phép miễn là chúng không ở vị trí ban đầu hoặc cuối cùng)
  • sau đó và chỉ sau đó JavaScript của bạn (có thể thực sự hoặc không phải là mã hợp lệ) sẽ được nhập lại dưới dạng Đối tượng hợp lệ. Bạn sẽ không được thông báo rằng mã của bạn đã được giải thích lại.

{wat:1}),({wat:2} Cuối cùng là một lỗi một lần nữa.

{let i=0;var increment=_=>i++} cuối cùng được cho phép một cách chính xác, đó là một cách khá hay để thực hiện việc đóng cửa.

Tuy nhiên, sau đây không chính xác là một đối tượng, đây chỉ là một sự tiện lợi như được đề cập bởi @Bergi, nó diễn giải sai JS để giúp bạn! Thông số kỹ thuật cho biết đây là một khối có câu lệnh được dán nhãn "foo" với nghĩa đen 1 không được gán cho bất cứ điều gì.

{foo:1}

Ở trên nên giống như

if(1) {
    foo: 1
}

Sau đây được coi là một khối ... bởi vì nó có một bình luận ở phía trước của nó!

//magic comment
{foo:1}

Đây là:

{foo:1}
//also magic

Đây là một đối tượng:

{foo:
//not so magic comment
1}

Đây là một lỗi

//not so magic comment
{foo:1}.foo

Đây là:

{foo:1}.foo

Điều này tốt

1..wat

undefined

đây là

['foo'][0]

Cái tiếp theo được hiểu chính xác là một đối tượng được đưa vào vị trí biểu thức với cái 0,mà nói chung là cách chúng ta rõ ràng đảm bảo rằng chúng ta có một biểu thức thay vì một câu lệnh.

0,{foo:1}.foo

Tôi không hiểu tại sao họ bọc giá trị trong parens. JS có một số quyết định thiết kế lố bịch, nhưng cố gắng làm cho nó hoạt động tốt hơn trong tình huống này không thực sự là một lựa chọn, giao diện điều khiển cần chạy JS chính xác và chúng tôi cần phải tự tin rằng chrome không chỉ đoán rằng nó nghĩ rằng chúng tôi nghĩ thực sự có nghĩa là nó để làm một cái gì đó khác.

Nếu bạn không thích toán tử dấu phẩy, bạn có thể sử dụng phép gán

x = {foo:1}.foo

Bởi vì khi nó đứng

{} + {} + {}

"[object Object][object Object][object Object]"

;{} + {} + {}

"NaN[object Object]"

Điên rồ và kiên định Tôi có thể đối phó với ... điên và không nhất quán không cảm ơn bạn!


REPL không phải là ngôn ngữ mà là REPL. Nó truyền chuỗi cho ngôn ngữ trong số những thứ khác . Đây là một số điều mà REPL của Chrome không có ngôn ngữ . Chúng khá hữu ích vì vậy tôi thực sự rất vui vì họ không gắn bó với ngôn ngữ đơn giản.
gman

@gman Một REPL Đọc một chuỗi, Đánh giá nó, In kết quả và sau đó chuẩn bị đọc đoạn mã động tiếp theo. Không có gì trong trang được liên kết là JavaScript không hợp lệ. Biến "$ _" nằm trong phạm vi giao diện điều khiển rõ ràng là một sự tiện lợi chỉ có ý nghĩa trong REPL. Tuy nhiên, "$ _" là một tên biến hợp lệ, phần còn lại chỉ là các hàm và lớp bình thường được gọi bằng JavaScript thông thường.
James Wakefield

Không chắc chắn quan điểm của bạn là gì. Quan điểm của tôi là ngôn ngữ là một thứ, môi trường mà nó chạy là một thứ khác. Bạn đã đưa ra một ví dụ trong câu trả lời của bạn. Trong JS {foo:1}{foo:1}//sản xuất điều tương tự. Trong REPL Chrome họ không. REPL đang làm nhiều hơn là chỉ đánh giá JS. Đó là xử lý các chuỗi và quyết định những thứ khác nhau.
gman

var x = eval('{a:1}')Trong JavaScript x hợp lệ bây giờ là 1, không phải là đối tượng trực quan hơn {a: 1}. Vâng, điều đó thật kỳ lạ, nhưng bạn không thể thay đổi ngôn ngữ vì nó làm những điều kỳ lạ. Mọi thứ ngoài chuỗi JSON đều được hiểu là JavaScript và được đánh giá. Việc nhập 0,trước khi dán JSON không khó, thay vào đó, tôi rất vui khi có cảnh báo rằng chuỗi được hiểu là một đối tượng thay vì JavaScript để thuận tiện.
James Wakefield
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.