2013-08-27 47 views
43

Chỉ là một câu hỏi nhanh về phạm vi biến JavaScript.Phạm vi biến vòng lặp JavaScript

Tại sao chức năng alert() in giá trị i thay vì trả lại undefined?

$(document).ready(function() { 
    for(var i = 0; i < 10; i += 1){ 
    } 

    alert("What is 'i'? " + i); 
}); 

Tôi khá mới để JS, và trong hầu hết các ngôn ngữ khác mà tôi đã học đòi, một tuyên bố trong phạm vi của vòng lặp for sẽ chứa các giá trị cho rằng vòng lặp cho biết, nhưng không phải trong trường hợp này, tại sao?

tức là What is 'i'? 10' được in.

Trả lời

55

Xem MDN cho "initialization parameters" của một for-loop:

Một biểu thức (bao gồm cả biểu thức phân) hoặc khai báo biến. Thường được sử dụng để khởi tạo biến số lượt truy cập. Biểu thức này có thể tùy ý khai báo các biến mới với từ khóa var. Các biến này không phải là cục bộ đối với vòng lặp, tức là chúng nằm trong cùng phạm vi với vòng lặp for. Kết quả của biểu thức này bị loại bỏ.

47

JavaScript không có phạm vi chặn, chỉ phạm vi chức năng. Kể từ khi khởi tạo của i là trong một chức năng, biến đó có thể truy cập bất cứ nơi nào khác trong cùng một chức năng.

Từ MDN:

Chú ý: JavaScript không có phạm vi khối. Các biến được giới thiệu với một khối được đưa vào phạm vi hàm hoặc kịch bản có chứa, và các hiệu ứng của việc thiết lập chúng tồn tại bên ngoài chính khối đó. Nói cách khác, các câu lệnh chặn không giới thiệu một phạm vi. Mặc dù các khối "độc lập" là cú pháp hợp lệ, bạn không muốn sử dụng các khối độc lập trong JavaScript, bởi vì chúng không làm những gì bạn nghĩ, nếu bạn nghĩ chúng làm bất cứ thứ gì như các khối như vậy trong C hoặc Java.

+0

Cảm ơn bạn đã nhập :) – BlackBox

+0

đây là khả năng tái tạo tuyệt vời nhưng phá vỡ những gì mặt trời đang cố gắng thiết lập. – simonarame

+1

@simonarame nhưng sau đó [Java và JavaScript không giống nhau] (https://stackoverflow.com/a/245068/3978545) nên không liên quan ... – Wolfie

9

Không giống như các ngôn ngữ khác (ví dụ: Java, C++, C), JavaScript không hỗ trợ phạm vi chặn. Khi bạn khai báo một biến trong một vòng lặp hoặc trong một chức năng đó là phạm vi nằm trong phạm vi cơ quan chức năng nếu bạn làm

for(i=0; i<arr.length; i++) { 
    var j=0; 
    // ... 
} 

đây bạn i trở thành một biến toàn cầu và j trở thành địa phương để các chức năng hoặc kịch bản, trong đó vòng lặp là .

8
for(i=0; i<arr.length; i++) { 
    var j=0; 
    // ... 
} 

không đúng khi nói ở trên tạo biến toàn cục i. Tôi tin rằng bạn nên luôn luôn sử dụng var để khai báo các biến (trừ khi bạn đang cố ý muốn một 'tài sản' thay vì 'biến' -những gì là không chắc chắn trong 99,99% các kịch bản mã JS ...)

Bỏ qua var khi gán giá trị ban đầu là i không tạo ra biến cục bộ hoặc thậm chí toàn cục, nó tạo ra một thuộc tính i cho đối tượng toàn cầu (có thể có vẻ/hoạt động chủ yếu giống như biến toàn cầu - nhưng chúng có một số khác biệt tinh tế).

tốt hơn sẽ là:

var i; 
for(i=0; i<arr.length; i++) { 
    var j=0; 
    // ... 
} 

nay là vòng lặp được sử dụng một biến toàn cầu i (hoặc chức năng biến địa phương i, nếu mã này xuất hiện trong một hàm)

xem chi tiết về vấn đề này tại what is function of the var keywordvariables vs. properties in Javascript

- lưu ý, một chút khó hiểu là bạn có thể khai báo lại biến, ví dụ như trong vòng lặp thứ hai

for(var i=0; i<9; i++){ 
    document.write('i = ' + i + '<br>'); 
} 


for(var i=0; i<9; i++){ 
    document.write('i = ' + i + '<br>'); 
} 

điều này có vẻ hợp lệ (không có lỗi khi tôi kiểm tra). Có vẻ như bạn CÓ THỂ tái khai báo biến trong JavaScript - nhưng có lẽ không phải là ý tưởng hay, trừ khi có trường hợp đặc biệt - hãy xem câu hỏi liên quan này đề cập đến cách [Google Analytics sử dụng 'redeclaration' an toàn '') Redeclaring a javascript variable)

có một số cuộc thảo luận về tái tuyên bố biến trong JS (và cũng có thể biến vòng lặp như i) trong liên quan SO câu hỏi này: declare variables inside or outside the loop

có trường hợp một JavaScript pattern for single declaration of variables

14

The folks javascript đang cố gắng để sửa lỗi này!

EcmaScript6 (aka EcmaScript 2015) là phiên bản mới nhất của javascript đã được chuyển vào mùa hè năm ngoái và các trình duyệt chỉ mới bắt đầu hỗ trợ các tính năng của nó.

Một trong những tính năng đó là các biến địa phương có phạm vi khối với biểu thức "cho phép". Kể từ bây giờ (tháng 4 năm 2016), hầu hết các phiên bản hiện tại của các trình duyệt chính đều hỗ trợ điều này ngoại trừ Safari. Rất ít trình duyệt di động hỗ trợ điều này.

Bạn có thể đọc thêm về nó ở đây (đặc biệt, hãy xem phần "let-scoped biến trong vòng lặp for"): https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let

Bạn có thể kiểm tra hỗ trợ trình duyệt hiện tại đây (tìm Bindings hàng -> let): https://kangax.github.io/compat-table/es6/

+0

cập nhật câu trả lời của bạn với nhiều thông tin hơn. spec là chính thức. cảm ơn –

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