2010-10-11 63 views
27

Nó không phải là thiết lập cho một trò đùa, tôi thực sự yêu cầu.Chuỗi Javascript không phải là đối tượng?

Douglas Crockford is fond of saying rằng trong ngôn ngữ hướng đối tượng prototypal javascript không cần new.

Ông giải thích rằng new được chỉ đơn giản là thêm vào để cung cấp cho những người đến từ (ví dụ: " cổ điển") hướng đối tượng ngôn ngữ lập trình dựa trên lớp một số mức độ thoải mái:

JavaScript, We Hardly new Ya

JavaScript là một ngôn ngữ nguyên mẫu, nhưng nó có một toán tử new cố gắng làm cho nó trông giống như một ngôn ngữ cổ điển. Điều đó có xu hướng gây nhầm lẫn cho các lập trình viên, dẫn đến một số mẫu lập trình có vấn đề.

Bạn không bao giờ cần sử dụng new Object() bằng JavaScript. Sử dụng đối tượng theo nghĩa đen {} để thay thế.

Được rồi, tiền phạt:

  • new xấu
  • {} tốt

Nhưng sau đó commenter Vítor De Araújo pointed out that the two are not the same. Ông đưa ra một ví dụ cho thấy rằng một string không giống như một object:

Một đối tượng chuỗi và một giá trị chuỗi không phải là điều tương tự:

js> p = "Foo" 
Foo 
js> p.weight = 42 
42 
js> p.weight // Returns undefined 

js> q = new String("Foo") 
Foo 
js> q.weight = 42 
42 
js> q.weight 
42 

Giá trị chuỗi không thể có đặc tính mới. Điều tương tự cũng hợp lệ đối với các loại khác.

Điều gì đang xảy ra ở đây là string không phải là object? Tôi có hiểu nhầm javascript với một số ngôn ngữ khác, nơi mọi thứ đều là một đối tượng không?

+0

... và tôi không hoàn toàn đồng ý với Crockford: nó không phải cần thiết để sử dụng 'new Object' (không phải là' new Array', sử dụng '[]' thay thế), nhưng nếu bạn muốn định nghĩa một thể hiện mới của một lớp được định nghĩa trước, bạn thực sự nên sử dụng toán tử 'new', như trong 'new Date()' hoặc 'new SchrodingersCat()'. –

+0

@Marcel Korpel: * "nên sử dụng" *, hoặc ** phải ** * sử dụng *? Có cách nào khác để xây dựng một đối tượng mới từ nguyên mẫu đối tượng 'Date' không? –

+0

Câu hỏi hay, trong trường hợp 'Ngày': ** phải **. Nếu bạn gọi 'Date' là một hàm rỗng, nó trả về ngày tháng và thời gian hiện tại dưới dạng một chuỗi. Ngoài ra, hãy xem [Sử dụng hàm tạo không có toán tử 'mới'] (http://stackoverflow.com/questions/1928342/using-constructor-without-operator-new) và [Toán tử mới của Javascript có làm gì ngoài việc làm cho cuộc sống khó khăn không?] (Http : //stackoverflow.com/questions/1744426/does-javascripts-new-operator-do-anything-but-make-life-difficult) –

Trả lời

57

"Mọi thứ đều là đối tượng" ... đó là một trong những quan niệm sai lầm lớn tồn tại xung quanh ngôn ngữ.

Khôngmọi thứ là một đối tượng, có những gì chúng ta gọi là giá trị nguyên thủy, đó là chuỗi, số, boolean, null, và không xác định.

Đúng vậy, một chuỗi là giá trị nguyên thủy, nhưng bạn có thể truy cập tất cả các phương thức được kế thừa từ String.prototype như thể đó là một đối tượng.

Thuộc tính accessor operators (dấu chấm và ký hiệu khung), tạm thời chuyển đổi giá trị chuỗi thành đối tượng Chuỗi để có thể truy cập các phương pháp đó, ví dụ::

"ab".charAt(1); // "b" 

gì xảy ra đằng sau hậu trường là một cái gì đó như thế này:

new String("ab").charAt(1); // "b", temporal conversion ToObject 

Như với các giá trị nguyên thủy khác, chẳng hạn như BooleanNumber, có đối tượng wrappers, mà chỉ đơn giản là các đối tượng chứa giá trị nguyên thủy, như trong ví dụ của bạn:

var strObj = new String(""); 
strObj.prop = "foo"; 

typeof strObj; // "object" 
typeof strObj.prop; // "string" 

Khi có mồi ive:

var strValue = ""; 
strValue.prop = "foo"; 

typeof strValue; // "string" 
typeof strValue.prop; // "undefined" 

Và điều này xảy ra bởi vì một lần nữa, các accessor tài sản trên dòng thứ hai ở trên, tạo ra một đối tượng thời gian mới, như:

var strValue = ""; 
new String(strValue).prop = "foo"; // a new object which is discarded 
//... 
+1

Tôi không muốn sử dụng chữ hoa với các chữ cái gốc, như 'boolean' và' number', để tránh sự nhầm lẫn với các trình bao bọc đối tượng 'Boolean' và' Số' (nhưng đặc tả ECMAScript không làm như vậy). Ngoài ra, 'NaN' cũng là một giá trị nguyên thủy. –

+0

Marcel, vâng, trình bao bọc đối tượng có thể gây nhầm lẫn, ví dụ: 'if (new Boolean (false)) {alert (': D');}'. Có, 'NaN', tích cực và âm' Infinity' là các giá trị của [Kiểu số] (http://ecma262-5.com/ELS5_HTML.htm#Section_8.5). – CMS

+1

Ah, vâng, 'Infinity', tôi đã nghĩ rằng tôi đã quên một số giá trị khác. Làm sao có thể quên được 'Infinity'? –

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