2012-01-30 35 views
7

Out of chỉ tò mò trí tuệ, tại sao javascript chấp nhậnJavascript: z = z || [] ném một lỗi khi không sử dụng VAR - tại sao?

var z = z || []; 

để khởi z (như z có thể được xác định ban đầu)

nhưng không var, nó ném một lỗi (trong không gian toàn cầu)

z = z || []; 

(nếu z trước đây chưa được xác định)

Trong không gian toàn cầu, bạn không bắt buộc phải sử dụng VAR mặc dù tôi nhận được nó có thể b e thực hành xấu.

Trước khi bạn nói điều này là bản sao của những câu hỏi như

What is the purpose of the var keyword and when to use it (or omit it)?

Note tuyên bố rằng "Nếu bạn đang ở trong phạm vi toàn cầu thì không có sự khác biệt."

Rõ ràng là không đúng 100%, ví dụ làm việc của tôi.

Đây có phải là một sự lừa đảo hoặc có logic hợp pháp không?


thêm một bản tóm tắt của câu trả lời là tôi đã học được nó:

Nhờ Tim (xem dưới đây) chìa khóa dẫn đến sự hiểu lầm của tôi đã không nhận ra điều này (cơ bản của javascript)

var z; hoàn toàn không có gì nếu z đã tồn tại

Đó là cách biểu thức này dường như có cả hai cách, nếu bạn cho rằng không đúng "var z" luôn khởi tạo.

Bắt đầu từ bên trái, "var z" chỉ cần đảm bảo z được xác định nhưng không thực sự ảnh hưởng đến bất kỳ giá trị hiện tại nào nếu nó đã tồn tại. Sau đó, bên phải, nếu z đã tồn tại, nó được sử dụng, nếu không, biến đã được khai báo (nhưng trống) vì vậy nó sẽ không được sử dụng nhưng sẽ không ném một lỗi.

Đây là một bài viết tuyệt vời về loại Phạm vi và cẩu vấn đề trong Javascript: http://www.adequatelygood.com/2010/2/JavaScript-Scoping-and-Hoisting

Nhiều nhờ minitech và mọi người khác đã đóng góp quá!

+2

Theo nguyên tắc chung: sao chép thông báo lỗi thực tế thường hữu ích hơn là chỉ viết "ném lỗi". –

Trả lời

6

z = z || [] sẽ ném vào bất kỳ phạm vi nào (toàn cầu hay không), trong đó không có z trong chuỗi phạm vi. Lý do cho điều này là biểu thức đầu tiên cố gắng truy lục giá trị của biến hiện tại có tên là z ở phía bên tay phải, đây là lỗi khi không tồn tại.

Lý do tại sao var z = z || [] không ném ra một lỗi là biến z được tạo ra (nếu nó chưa tồn tại) trước khi biểu thức được thực thi, một hiệu ứng thường được gọi là cẩu. Mặt khác, gán giá trị cho một số nhận dạng chưa được giải quyết (ví dụ: z = 2) sẽ hoạt động mà không có lỗi trong bất kỳ phạm vi nào (ngoại trừ trong chế độ nghiêm ngặt ECMAScript 5, sẽ cấm và ném). Nếu mã định danh không thể được giải quyết, nó sẽ được thêm vào như là một thuộc tính của đối tượng cuối cùng trong chuỗi phạm vi, là đối tượng chung, do đó tạo ra sự xuất hiện của việc tạo ra một biến toàn cầu.

+0

Ah, tôi nghĩ mình đã hiểu rồi. Vì vậy, "var z" được thực hiện đầu tiên ở phía bên trái, giống như hướng dẫn "tạo một z mới" nhưng sau đó nó sẽ tìm một "old z" ở phía bên phải. Theo thứ tự đó, "z" vừa được khởi tạo ở bên trái, vì vậy "z" ở bên phải không được xác định, mặc dù nó trống. Không có var, "z" ở bên phải không chỉ trống, nó không được xác định. Hmm okay - nếu "var z" định nghĩa nó là mới ở bên trái, làm thế nào mã này bảo toàn các giá trị hiện có? Có vẻ như nó có cả hai cách, khởi tạo bên trái cho bên phải, nhưng cũng có thể giữ giá trị ở bên phải. –

+0

@ck_: Vâng, tôi nghĩ bạn đã có nó, mặc dù thuật ngữ cần được chăm sóc bởi vì 'undefined' là giá trị thực trong JavaScript và thực tế là giá trị mặc định được gán cho một biến (ví dụ,' var x; ' tạo một biến gọi là 'x' với giá trị ban đầu là' undefined', khác biệt với 'x' không tồn tại chưa được khai báo). Tôi muốn tìm "không khai báo" hoặc "không tồn tại". –

+0

@ck_: Về việc bảo tồn các giá trị hiện có, 'var z;' hoàn toàn không có gì nếu 'z' đã tồn tại, bất kể giá trị của nó. –

10

Hiệu quả là chính xác. var sẽ luôn luôn khai báo "toán hạng" ngay lập tức, trong khi khi bạn không khai báo nó, tập lệnh của bạn cố gắng sử dụng biến không xác định và đưa ra lỗi.

Nếu bạn đang ở trong phạm vi toàn cầu, bạn có thể gán cho một biến không tồn tại và nó sẽ có tác dụng tương tự như tuyên bố nó, thực hành xấu như vậy có thể. Tất nhiên, trong trường hợp của bạn, nó không xác định.Đây đang được nói, mặc dù nó có thể là vì tò mò trí tuệ, bạn sẽ không bao giờ viết

var z = z || []; 

vì nó làm cho không có ý nghĩa để làm như vậy. Thay vào đó, bạn có thể làm:

if(!window.z) { 
    window.z = []; 
} 

. Trong thực tế, khi tôi tuyên bố mọi thứ trong phạm vi toàn cầu (không bao giờ là ;)), tôi sử dụng window.something thay vì nó làm cho ý định của tôi rõ ràng hơn.

+0

** khi bạn không khai báo nó, tập lệnh của bạn cố gắng sử dụng biến không xác định ** - đợi bạn đang nói z = z truy cập z nhưng var z = z thì không? Số thứ hai z vẫn nằm trong phạm vi toàn cục, là đầu tiên nếu nó nằm ngoài một hàm. (khó hiểu) –

+1

@ck_: Sự khác biệt là sử dụng 'var' làm biến' z' được tạo trước khi bất kỳ câu lệnh nào được thực hiện. –

4

Bạn có thể gán cho biến chưa được khai báo z = 123; tuy nhiên, bạn có thể không cố gắng đọc một trong đó là những gì mà z = z || [] thực hiện.

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