Tại sao JavaScript lưu trữ các biến?


95

Tại sao JavaScript lưu trữ các biến?

Cơ sở lý luận của các nhà thiết kế khi họ quyết định thực hiện vận thăng là gì? Có ngôn ngữ phổ biến nào khác làm được điều này không?

Vui lòng cung cấp các liên kết liên quan đến tài liệu và / hoặc hồ sơ.


7
Tại thời điểm này, tôi nghi ngờ rằng đó là lịch sử và tôi thực sự nghi ngờ nó là bất cứ điều gì khác hơn là "dễ thực hiện" ban đầu.
Dave Newton

4
Thành thật mà nói, hãy hỏi Brendan Eich, anh ấy có vẻ khá đáp ứng.
Felix Kling

23
Câu hỏi này không mang tính xây dựng như thế nào?
Francisc

19
Hoan nghênh @Francisc để Stack Overflow, nơi tất cả các bạn có thể hỏi về được di chuyển một divtrong jQuery
Xlaudius

21
Đây là một câu hỏi thực sự quan trọng. Nó đáng lẽ phải được cho phép. Nó không phải mồi lửa. Hoisting là một trong những yếu tố cốt lõi để hiểu cách hoạt động của JavaScript và "tại sao" là một câu hỏi chính đáng được giải quyết trong hầu hết các phương pháp điều trị trong sách giáo khoa về ngôn ngữ này. Sẽ là KHÔNG ĐƯỢC khi mọi người của Stack Overflow CHỈ CÓ THỂ trả lời những câu hỏi của mọi người như thế này.
bearvarine

Câu trả lời:


55

Như Stoyan Stefanov giải thích trong cuốn sách "Các mẫu JavaScript", quá trình lưu trữ là kết quả của việc triển khai trình thông dịch JavaScript.

Việc diễn giải mã JS được thực hiện trong hai lần. Trong lần truyền đầu tiên, trình thông dịch xử lý các khai báo biến và hàm.

Bước thứ hai là bước thực thi mã thực tế. Trình thông dịch xử lý các biểu thức hàm và các biến chưa được khai báo.

Do đó, chúng ta có thể sử dụng khái niệm "cẩu" để mô tả hành vi đó.


15
Cá nhân tôi thực sự không thích từ "cẩu". Nó đưa ra biểu diễn sai rằng các khai báo biến và hàm được đưa lên đầu phạm vi hiện tại một cách kỳ diệu, trong khi thực tế, trình thông dịch JS, như bạn đã đề cập, quét mã nguồn cho các liên kết và sau đó thực thi mã.
contactmatt

Bây giờ tôi đã hiểu tại sao ngôn ngữ JS bị hiểu nhầm nhiều nhất, tôi không thấy điều này trong bất kỳ hướng dẫn nào. Và bị nhầm lẫn với cẩu (và lưu lượng tương tác).
Swapnil Patwa

18
Uh, điều này không thực sự giải thích lý do. Một trình thông dịch một lần (điều đó sẽ không dẫn đến việc cẩu) sẽ đơn giản hơn nhiều - vậy tại sao các nhà thiết kế lại chọn hai lần?
Bergi

1
Điều này không giải thích tại sao các biến, cụ thể là được nâng lên. Các hàm có ý nghĩa, các biến thì không (trong hầu hết các trường hợp) - Tôi tin rằng đó là một lỗi.
Josh M.

1
Josh M. này rất rộng rãi quy định, tôi không nghĩ rằng đây là một "lỗi" ... (Tôi đồng ý rằng câu trả lời điều này không thực sự trả lời lập luận dù)
Jonas Wilms

11

Người tạo JS, Brendan Eich đã từng nói (trên Twitter) :

"var hoisting do đó [là] hậu quả không mong muốn của chức năng hoisting, không có phạm vi khối, [và] JS là một công việc gấp rút năm 1995."

Anh ấy cũng giải thích rằng…

"function hoisting cho phép phân rã chương trình từ trên xuống, 'let rec' miễn phí, gọi trước khi khai báo; var hoisting được gắn thẻ cùng."

Brendan Eich

Có ngôn ngữ phổ biến nào khác làm được điều này không?

Tôi không biết bất kỳ ngôn ngữ phổ biến nào khác sử dụng các biến theo cách tương tự. Tôi nghĩ rằng ngay cả ActionScript - một triển khai khác của ECMAScript được sử dụng trong phát triển Flash - cũng không triển khai tính năng lưu trữ. Điều này đã gây ra sự nhầm lẫn và thất vọng cho các nhà phát triển quen thuộc với các ngôn ngữ khác đang học JavaScript.

CẬP NHẬT: Từ các nhận xét, Python có hành vi cẩu biến tương tự .


2
Đưa ra +1 vì đây là câu trả lời duy nhất cố gắng giải quyết trực tiếp câu hỏi.
Damon

1
Cảm ơn bạn vì câu trả lời này. Tôi hoàn toàn đồng ý với @Damon!
codingbryan

1
Một ngôn ngữ phổ biến khác có lưu trữ biến là Python: stackoverflow.com/q/63337235/2326961
Maggyero

2

Điều này là do trình thông dịch javascript thông dịch mã trong hai chu kỳ.

  1. Hoàn thành / biên dịch mã:
  2. Thực thi mã:

Trong chu kỳ đầu tiên, tất cả các khai báo biến và hàm được đưa lên đầu phạm vi hàm mà nó đang thực thi. Điều này giúp tạo variableObjectscho execution contexthàm ngay cả trước khi nó thực thi.

Trong giai đoạn 2, các phép gán giá trị, câu lệnh mã và lệnh gọi hàm diễn ra từng dòng theo cách thức mong đợi.

Bạn có một chút chi tiết hơn đọc ở đây.

Nó sẽ cung cấp cho bạn một hình ảnh tốt hơn xung quanh xung quanh hành vi let, constclasstờ khai, cũng là ưu tiên nó sau giữa biến và chức năng.


1
Bạn đang ngụ ý rằng đó là hệ quả của một sự lựa chọn thiết kế? Nếu vậy, bạn nên nói rõ điều đó trong câu trả lời của mình. Nhưng đọc câu trả lời của Brendan Eich, nó có thể là một đặc điểm bị truy nã, nó phụ thuộc vào cách bạn diễn giải câu cuối cùng. Tóm lại, tôi vẫn không biết chắc chắn tại sao
Bombinosh
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.