Tại sao giá trị của typeof null thay đổi bên trong một vòng lặp?


109

Thực thi đoạn mã này trong bảng điều khiển Chrome:

function foo() {
    return typeof null === 'undefined';
}
for(var i = 0; i < 1000; i++) console.log(foo());

nên in 1000 lần false, nhưng trên một số máy sẽ in falsecho một số lần lặp, sau đó truecho phần còn lại.

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

Tại sao chuyện này đang xảy ra? Nó chỉ là một lỗi?


4
Nó đang trở lại đúng 1000 lần với tôi ...
Hoàng Long

2
tôi nghĩ rằng đó là lỗi, tôi có 262 sai / 738 đúng
Jax Teller

1
đó là một cái gì đó kỳ lạ với bảng điều khiển của chrome: nếu bạn đẩy đến một mảng và ghi lại mảng đó, tất cả chỉ là false. hiện tại, số trues dao động trong chrome.
dandavis

1
@ HoàngLong như mình đã nói ở câu hỏi thì chỉ xảy ra trên một số máy thôi. Cũng có thể điều đó chỉ xảy ra trên một số phiên bản của Chrome
Agos

2
@ HoàngLong đảm bảo bạn đang chạy nó trên Chrome
Nobita

Câu trả lời:


74

Có một lỗi crôm mở cho điều này:

Sự cố 604033 - Trình biên dịch JIT không bảo toàn hành vi của phương thức

Vì vậy, có Nó chỉ là một lỗi!


5
"Chỉ"? Điều này không thể phá vỡ các ứng dụng web tùy ý trên toàn thế giới?
jpmc 26

6
"Chỉ là" chỉ để nói rằng đó không phải là một tính năng hoặc một cái gì đó lạ. Là một lỗi nghiêm trọng, nhưng chỉ là một lỗi!
Slumber86

37

Nó thực sự là một lỗi công cụ JavaScript V8 ( Wiki ).

Công cụ này được sử dụng trong Chromium, Maxthron, Android OS, Node.js, v.v.

Mô tả lỗi tương đối đơn giản mà bạn có thể tìm thấy trong chủ đề Reddit này :

Các công cụ JavaScript hiện đại biên dịch mã JS thành mã máy được tối ưu hóa khi nó được thực thi (biên dịch Just In Time) để làm cho nó chạy nhanh hơn. Tuy nhiên, bước tối ưu hóa có một số chi phí hiệu suất ban đầu để đổi lấy tốc độ lâu dài, do đó, động cơ quyết định xem một phương pháp có xứng đáng hay không tùy thuộc vào mức độ phổ biến của nó.

Trong trường hợp này, dường như chỉ có một lỗi trong đường dẫn được tối ưu hóa, trong khi đường dẫn chưa được tối ưu hóa hoạt động tốt. Vì vậy, lúc đầu phương pháp này hoạt động như dự định, nhưng nếu nó được gọi trong một vòng lặp đủ thường xuyên vào một thời điểm nào đó, động cơ sẽ quyết định tối ưu hóa nó và thay thế nó bằng phiên bản lỗi.

Lỗi này dường như đã được sửa trong chính V8 ( cam kết ), cũng như trong Chromium ( báo cáo lỗi ) và NodeJS ( cam kết ).


Tôi xác nhận rằng lỗi vẫn còn trong Node.js 6.2.2 khiến tôi lo lắng.
Michael Shopsin

Nó đã được sửa trong động cơ V8 hôm nay (21.06), tôi tin rằng phần mềm liên quan sẽ sớm được cập nhật.
Sergey Novikov

Việc sao lưu bản sửa lỗi v8 sang Node.js 6.2.x đang được tiến hành vì sự cố # 7348 thuộc sở hữu của TheAlphaNerd .
Michael Shopsin

18

Để trả lời câu hỏi trực tiếp về lý do tại sao nó thay đổi, lỗi nằm trong quy trình tối ưu hóa "JIT" của động cơ V8 JS được Chrome sử dụng. Lúc đầu, mã được chạy chính xác như được viết, nhưng bạn càng chạy nó, thì càng có nhiều khả năng lợi ích của việc tối ưu hóa vượt quá chi phí phân tích.

Trong trường hợp này, sau khi thực hiện lặp lại trong vòng lặp, trình biên dịch JIT phân tích hàm và thay thế nó bằng một phiên bản được tối ưu hóa. Thật không may, phân tích đưa ra một giả định không chính xác và phiên bản được tối ưu hóa không thực sự tạo ra kết quả chính xác.

Cụ thể, người dùng Reddit RainHappens cho rằng đó là lỗi trong việc truyền kiểu :

Nó cũng thực hiện một số kiểu lan truyền (như kiểu mà một biến, v.v. có thể là). Có một loại "không thể phát hiện" đặc biệt khi một biến không xác định hoặc null. Trong trường hợp này, trình tối ưu hóa đi "null không thể phát hiện được, vì vậy nó có thể được thay thế bằng chuỗi" không xác định "để so sánh.

Đây là một trong những vấn đề khó khăn với việc tối ưu hóa mã: làm thế nào để đảm bảo rằng mã đã được sắp xếp lại để đạt được hiệu suất sẽ vẫn có tác dụng như ban đầu.


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.