2012-01-05 42 views
10

Tôi bị nhầm lẫn sâu sắc bởi hành vi của JavaScript hoặc bảng điều khiển Chrome. Ai đó có thể giúp tôi hiểu không?Bảng điều khiển JavaScript in giá trị được gán của biến trước khi nó được gán?

Về cơ bản tôi đã mã JavaScript sau, không lồng vào bên trong bất kỳ chức năng hoặc phạm vi khác:

var initial_array = []; 

function initialiseArray() { 
    initial_array = [2, 9, 8, 6, 0, 2, 1]; 
} 

function copyToNewArray() { 
    var copied_array = []; 

    console.log("COPIED 1", copied_array); 

    for (var i = 0; i < initial_array.length; i++) { 
     var copy = initial_array[i]; 
     copied_array.push(copy); 
    } 

    console.log("COPIED 2", copied_array); 
} 

initialiseArray(); 
copyToNewArray(); 

Tôi mong chờ COPIED 1 in [] - là biến chưa được gán chưa - nhưng thay vào đó nó in [2, 9, 8, 6, 0, 2, 1] - tức là giá trị sau khi nó được gán.

Tại sao?

Ngẫu nhiên, nếu bạn thay thế dòng 8-11 bằng initial_array = copied_array thì RESULTS 1 thực sự in là []. Có liên quan gì đến việc sử dụng .push không?

+0

Thú vị. Điều này dường như giải quyết cùng một vấn đề? [link] (http://zef.me/2843/javascript-the-scope-pitfall) – j08691

+4

câu hỏi tương tự: http://stackoverflow.com/questions/4057440/is-chromes-javascript-console-lazy-about- đánh giá-mảng – diEcho

Trả lời

8

Hãy thử gỡ vấn đề của bạn trong trình gỡ lỗi script Chrome.Đặt điểm ngắt trên đường:

for (var i = 0; i < initial_array.length; i++) { 

và bạn sẽ thấy hành vi mà bạn mong muốn.

Sự cố bạn đang gặp phải là bạn đang đưa ra giả định không chính xác rằng trình gỡ lỗi Chrome 'in' giá trị ngay lập tức khi thực tế nó không đồng bộ console.log. Kể từ khi mảng được thông qua xung quanh bằng cách tham khảo trong phụ trợ khi nó thực sự đi để in giá trị nó bây giờ là một trong những bạn đang nhìn thấy.

+0

Đề xuất tốt cho trình gỡ lỗi tập lệnh Chrome, tôi đã thử với trình gỡ lỗi Webstorm mà không cần nhiều thành công. – Osy

+0

Câu trả lời hay ... LAME logger :( – Nicole

0
var initial_array = []; 
function initialiseArray() { 
    initial_array = [2, 9, 8, 6, 0, 2, 1]; 
} 
function copyToNewArray() { 
    var copied_array = []; 
    console.log("COPIED 1", copied_array); 
    alert(copied_array.length); 
    for (var i = 0; i < initial_array.length; i++) { 
     var copy = initial_array[i]; 
     copied_array.push(copy); 
    } 
    console.log("COPIED 2", copied_array); 
} 
initialiseArray(); 
copyToNewArray(); 

Thêm dòng alert(copied_array.length); sẽ hiển thị kết quả chính xác.

Điều gì xảy ra là nhật ký không được đồng bộ hóa với thực thi javascript. Khi nhật ký in các giá trị đã được thay đổi.

1

Đó là cách các mảng được hiển thị trong bảng điều khiển Chrome và đó là theo tham chiếu. Nếu bạn muốn kết quả chính xác, chuyển đổi thành một chuỗi:

var initial_array = []; 

function initialiseArray() { 
    initial_array = [2, 9, 8, 6, 0, 2, 1]; 
} 

function copyToNewArray() { 
    var copied_array = []; 

    console.log("COPIED 1", copied_array.toString()); 

    for (var i = 0; i < initial_array.length; i++) { 
     var copy = initial_array[i]; 
     copied_array.push(copy); 
    } 

    console.log("COPIED 2", copied_array.toString()); 
} 

initialiseArray(); 
copyToNewArray(); 

Bạn có thể kiểm tra điều này ra khá dễ dàng:

var x = []; 
console.log(x), x.push(5), x; // outputs [5] and [5] 
+0

Tuy nhiên, bạn nghĩ rằng nó sẽ render/stringize/giải quyết tham chiếu mảng tại điểm thích hợp, nếu không 'console.log'ging mảng sẽ khá nhiều không bao giờ làm việc. Firefox có chịu thua hay không, hay nó thông minh hơn? –

+0

@LightnessRacesinOrbit: Không thông minh hơn, nhưng thay vì chuyển đổi mọi thứ thành chuỗi, vì vậy có nó sẽ hoạt động. (FireBug, mặt khác ... Tôi không chắc chắn.) – Ryan

+0

Tôi đề nghị rằng _is_ "thông minh hơn", bởi vì giữ tham chiếu bị ràng buộc quá muộn trong trường hợp này rõ ràng vi phạm POLS. (FWIW, tôi muốn nói Firebug) –

1

Giao diện điều khiển là thực sự không đồng bộ. Bởi vì bạn đang đăng nhập một tham chiếu đến một đối tượng, vào thời điểm đối tượng được ghi lại nó đã thay đổi.

Bạn có thể sao chép mảng trước khi đăng nhập để chắc chắn rằng nó không bị thay đổi trước khi được ghi nhật ký.

3

Vì mảng được chuyển theo tham chiếu, mọi thay đổi bạn thực hiện với nó sẽ thay đổi đầu ra trong bảng điều khiển. Đó là một phần hành vi của bảng điều khiển của Chrome, một phần của JavaScript.

Nếu bạn muốn in kết quả tại thời điểm cuộc gọi đến console.log, bạn có thể xuất kết quả dưới dạng chuỗi sử dụng JSON.stringify.

console.log("COPIED 1", JSON.stringify(copied_array)); 

chỉnh sửa quan trọng

Có vẻ như tôi đã chủ yếu là sai. Như diEcho được chỉ ra trong các nhận xét của câu hỏi, một similar question có một số better answer. Dường như chỉ là hành vi của Chrome.

+0

Tôi cũng tìm thấy hành vi này trong bảng điều khiển dành cho nhà phát triển web firefox (trình duyệt chứng khoán không phải là firebug). Vì vậy, có lẽ nó không chỉ là một hành vi của Chrome. –

0

là do copied_array là tham chiếu và console.log được thực thi theo cách đồng bộ, do đó nội dung của mảng được sửa đổi trước khi nhật ký đầu tiên in.

bạn có thể sao chép mảng trước khi in

console.log([].concat(copied_array)); 
0

Nếu bạn muốn giữ lại chức năng của giao diện điều khiển như mở rộng các đối tượng trong một mảng, tôi đề nghị sử dụng .slice, mà làm cho một bản sao của mảng mà không thay đổi khi đăng nhập :

console.log("COPIED 1", copied_array.slice()); 
+0

Tốt nhưng phương pháp JSON.stringify (copied_array) có vẻ tốt hơn, tôi nghĩ vậy. –

Các vấn đề liên quan