Tôi thấy rằng một số người gọi JavaScript là một ngôn ngữ "được gõ động, được gõ yếu", nhưng một số người thậm chí còn nói "chưa được gõ"? Nó thực sự là gì?
Tôi thấy rằng một số người gọi JavaScript là một ngôn ngữ "được gõ động, được gõ yếu", nhưng một số người thậm chí còn nói "chưa được gõ"? Nó thực sự là gì?
Câu trả lời:
JavaScript không được định kiểu:
(nguồn: no.gd )
Ngay cả Brendan Eich cũng nói như vậy. Trên Twitter, anh ấy đã trả lời một chủ đề liên quan đến câu hỏi này:
... các kiểu học thuật sử dụng "không định kiểu" có nghĩa là "không có kiểu tĩnh" ...
Vì vậy, vấn đề là có một vài định nghĩa khác nhau về không định kiểu .
Một định nghĩa đã được nói đến trong một trong các câu trả lời ở trên - thời gian chạy không gắn thẻ các giá trị và chỉ coi mỗi giá trị là các bit. JavaScript thực hiện các giá trị thẻ và có các hành vi khác nhau dựa trên các thẻ đó. Vì vậy, JavaScript rõ ràng không phù hợp với danh mục này.
Định nghĩa khác là từ Lý thuyết ngôn ngữ lập trình (thứ học thuật mà Brendan đang đề cập đến). Trong miền này, không định kiểu chỉ có nghĩa là mọi thứ thuộc về một kiểu duy nhất .
Tại sao? Bởi vì một ngôn ngữ sẽ chỉ tạo ra một chương trình khi nó có thể chứng minh rằng các kiểu phù hợp (hay còn gọi là tương ứng Curry-Howard ; kiểu là định lý, chương trình là chứng minh). Điều này có nghĩa là trong một ngôn ngữ không định kiểu:
Ngược lại với ngôn ngữ đã nhập:
Vì vậy, bạn hiểu rồi đấy, trong PLT, không định kiểu chỉ có nghĩa là nhập động và đã gõ chỉ có nghĩa là nhập tĩnh . JavaScript chắc chắn không được gõ trong danh mục này.
Xem thêm:
1. 2. 3.
cho một ngôn ngữ chưa định kiểu không khớp với JavaScript. Không chỉ có một kiểu - có khoảng 4 - 5. Vậy làm thế nào để chứng minh JavaScript không có kiểu?
mạnh / yếu có thể được xem xét liên quan đến cách trình biên dịch, nếu có, xử lý việc nhập.
Nhập yếu có nghĩa là trình biên dịch, nếu có, không thực thi nhập chính xác. Nếu không có sự can thiệp của trình biên dịch ngầm định, lệnh sẽ bị lỗi trong thời gian chạy.
"12345" * 1 === 12345 // string * number => number
Được gõ mạnh có nghĩa là có một trình biên dịch và nó muốn bạn truyền từ chuỗi sang số nguyên một cách rõ ràng.
(int) "12345" * 1 === 12345
Trong cả hai trường hợp, một số tính năng của trình biên dịch có thể thay đổi hoàn toàn hướng dẫn trong thời gian biên dịch để thực hiện chuyển đổi cho bạn, nếu nó có thể xác định đó là điều đúng đắn cần làm.
Cho đến nay, JavaScript có thể được phân loại là Không được đánh máy mạnh. Điều đó có nghĩa là nó được gõ yếu hoặc không được gõ.
động / tĩnh có thể được coi là liên quan đến cách các hướng dẫn ngôn ngữ thao tác các kiểu.
Được nhập động nghĩa là kiểu của giá trị được thực thi, nhưng biến chỉ đơn giản là đại diện cho bất kỳ giá trị nào thuộc bất kỳ kiểu nào.
x = 12345; // number
x = "string"; // string
x = { key: "value" }; // object
y = 123 + x; // error or implicit conversion must take place.
Được nhập tĩnh có nghĩa làkiểu biến được thực thi mạnh mẽ và kiểu giá trị ít được thực thi hơn.
int x = 12345; // binds x to the type int
x = "string"; // too late, x is an integer - error
string y = 123; // error or implicit conversion must take place.
Cho đến nay, JavaScript có thể được phân loại là Không tĩnh. Ngoài ra, nó dường như được gõ động, nếu được nhập. Vì vậy, chúng ta cần xem Typing có nghĩa là gì.
Đã nhập có nghĩa là ngôn ngữ phân biệt giữa các kiểu khác nhau như chuỗi , số , boolean , đối tượng , mảng , null , không xác định , v.v. Ngoài ra, mỗi hoạt động được ràng buộc với các loại cụ thể. Vì vậy, bạn không thể chia một số nguyên cho một chuỗi .
2 / "blah" // produces NaN
Không định kiểu có nghĩa là hoạt động chia số nguyên cho chuỗi sẽ dẫn đến việc coi bốn byte đầu tiên của chuỗi là số nguyên . Điều này là do các hoạt động không định kiểu diễn ra trực tiếp trên các bit, không có kiểu nào để quan sát. Kết quả sẽ là một cái gì đó khá bất ngờ:
2 / "blah" // will be treated as 2 / 1500275048
Vì JavaScript hoạt động theo định nghĩa được gõ, nên nó phải như vậy. Và do đó, nó phải được gõ động, và gõ yếu.
Nếu ai đó tuyên bố JavaScript là Untyped, nó chỉ là lý thuyết hàn lâm, không phải ứng dụng thực tế.
JavaScript được gõ yếu . Nó chắc chắn không phải là "không định kiểu" nhưng bản chất được đánh máy yếu của nó cho phép rất linh hoạt về chuyển đổi ngầm định.
Hãy nhớ rằng JavaScript cũng được nhập động. Phương pháp gõ này cho phép những gì được gọi là "gõ vịt" .
Để so sánh, hãy cân nhắc rằng JavaScript không được gõ mạnh cũng như không được gõ tĩnh. Đôi khi hiểu điều gì đó không có thể giúp bạn nhìn rõ hơn nó là gì.
Theo quan điểm của tác giả, JavaScript cũng được phân loại là Kiểu gõ động . Wiki tuyên bố rằng các ngôn ngữ được gõ động được kiểm tra kiểu trong thời gian chạy thay vì trong trình biên dịch trong khi kiểu gõ yếu đề cập đến khả năng thay đổi kiểu ngay lập tức trong mã của bạn. Vì vậy, có, nó được gõ cả động và gõ yếu.
Vấn đề ở đây làm cho rất nhiều lập trình viên bối rối là các định nghĩa như thế này không được chuẩn hóa ở đâu đó. Thuật ngữ ngôn ngữ lập trình không định kiểu là mơ hồ. Điều đó đề cập đến một ngôn ngữ không có kiểu dữ liệu hoặc một ngôn ngữ là một biến thể không định kiểu của phép tính giải tích lambda ?
JavaScript / ECMAScript có một hệ thống kiểu và tất cả các miền của chức năng của nó sẽ chấp nhận bất kỳ kiểu đặc tả Tham chiếu nào. Vì vậy, điều đó có nghĩa là JavaScript có một kiểu dữ liệu duy nhất, trong thực tế. Đó là vấn đề triển khai quan trọng hơn đối với các lập trình viên JavaScript rất cao cấp. Các lập trình viên JavaScript trung bình chỉ quan tâm đến các kiểu dữ liệu ngôn ngữ trừu tượng đã được chỉ định bởi ECMAScript.
Trong bối cảnh của các lập trình viên hàng ngày, không phải là nhà nghiên cứu hay nhà khoa học máy tính lý thuyết, thuật ngữ không định kiểu là một từ nhầm lẫn vì hầu hết mọi người không làm phép tính lambda. Do đó, thuật ngữ này gây nhầm lẫn cho nhiều người và dường như tuyên bố rằng JavaScript không có bất kỳ kiểu dữ liệu nào đơn giản là không đúng. Bất kỳ ai đã từng sử dụng typeof
đều biết rằng JavaScript có các kiểu dữ liệu ngôn ngữ riêng của nó:
var test = "this is text";
typeof(test);
hoa lợi
"chuỗi"
ECMAScript định nghĩa các loại sau đây cho ngôn ngữ: undefined
, null
, string
, boolean
, number
,object
http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf
Một ký hiệu chính xác hơn cho JavaScript sẽ được nhập ngầm, nhập động, hoặc nhập yếu / lỏng lẻo (hoặc một số kết hợp của chúng), trong đó JavaScript sử dụng kiểu ép buộc trong một số trường hợp, điều này làm cho kiểu ẩn vì bạn không phải chỉ định rõ ràng loại biến của bạn. Nó được nhập yếu bởi vì, không giống như một số ngôn ngữ phân biệt giữa float và integer, v.v., nó chỉ sử dụng một number
kiểu để bao gồm tất cả các số và sử dụng kiểu ép buộc đã đề cập trước đây [Phần 9 của ECMAScript Spec] , trái ngược hẳn với ngôn ngữ được đánh máy mạnh sẽ có các kiểu dữ liệu rất cụ thể (tức là bạn sẽ phải chỉ định int
hoặc float
).
Các định nghĩa của ngôn ngữ gõ tĩnh và động không được chuẩn hóa, tuy nhiên kích thước của một byte cũng không phải là khi máy tính bắt đầu phát triển. Nhập tĩnh và nhập động thường đề cập đến sự hiện diện của các tính năng ngôn ngữ nhất định. Một trong số đó là kiểm tra kiểu trong thời gian chạy , hay còn gọi là kiểm tra kiểu động . Nếu bạn đã sử dụng JavaScript, bạn đã biết rằng nó chắc chắn sẽ đợi đến thời gian chạy để kiểm tra các loại, đó là lý do tại sao bạn nhận được TypeError
ngoại lệ trong quá trình thực thi mã của mình. Ví dụ ở đây
Tôi nghĩ rằng câu trả lời được bình chọn nhiều nhất đang gây nhầm lẫn giữa tính đa hình của các hàm JavaScript với các hàm sẽ chấp nhận mọi thứ theo nghĩa đen (như với các biến thể không định kiểu của Lambda Calculus) là một sai lầm của Hiệp hội .
Hãy nhớ rằng JavaScript cho phép bạn hỏi cái gì là typeof(your_variable)
và so sánh các loại: 5==="5"
trả về false
. Vì vậy, tôi không nghĩ bạn có thể gọi nó là không định kiểu.
Nó được gõ động và (ước tính là) yếu. Bạn có thể muốn biết nó sử dụng kiểu gõ Duck (xem liên kết của andrew) và cung cấp OOP thông qua Prototyping thay vì các lớp và kế thừa.
String a = "blah";
hoặc var a:String = 'blah';
(tức là các biến đã nhập). Đó là lý do tại sao nó không được định kiểu.
Trong khi nó được gõ (bạn có thể hỏi "typeof someVar" và tìm hiểu kiểu cụ thể của nó, nó rất yếu.
Được:
var a = "5";
bạn có thể nói rằng a là một chuỗi. Tuy nhiên, nếu sau đó bạn viết:
var b = a + 10;
b là một int bằng 15, vì vậy a hoạt động giống như một int. Tất nhiên, sau đó bạn có thể viết:
var c = a + "Hello World";
và c sẽ bằng "5Hello World", vì vậy a lại hoạt động giống như một chuỗi.