2013-07-30 19 views
8

Hôm nay tôi tình cờ có quá nhiều thời gian để giết và tôi đã chơi một chút với dòng lệnh Node (v0.10.13):Tại sao JavaScript nguyên thủy không phải là đối tượng của đối tượng?

> 1 instanceof Object 
false 
> (1).__proto__ 
{} 
> (1).__proto__ instanceof Object 
true 
> (1).__proto__.__proto__ === Object.prototype 
true 

Bây giờ, theo MDN, những gì instanceof làm là:

Toán tử instanceof kiểm tra xem một đối tượng có trong chuỗi nguyên mẫu nguyên mẫu của một hàm tạo hay không.

Nhưng rõ ràng là Object.prototype IS trong chuỗi nguyên mẫu của 1. Vậy tại sao 1 instanceof Object là sai? Có lẽ vì 1 là một nguyên thủy không phải là một đối tượng để bắt đầu?

Được rồi, tôi chấp nhận điều đó, và tôi đã làm thêm các xét nghiệm:

> (1).__proto__ === (2).__proto__ 
true 
> 'a'.__proto__ === 'b'.__proto__ 
true 
> (1).__proto__ === 'a'.__proto__ 
false 
> (1).__proto__.__proto__ === 'a'.__proto__.__proto__ 
true 
> (1).__proto__.type = 'number' 
'number' 
> 'a'.__proto__.type = 'string' 
'string' 
> (2).type 
'number' 
> (1.5).type 
'number' 
> 'b'.type 
'string' 

Vì vậy, dường như tất cả nguyên thủy số kế thừa từ một đối tượng, và tất cả các chuỗi nguyên thủy kế thừa từ một đối tượng khác. Cả hai đối tượng này đều được kế thừa từ Object.prototype.

Bây giờ câu hỏi đặt ra là, nếu số và chuỗi được coi là nguyên thủy, tại sao kế thừa chúng từ các đối tượng khác? Hoặc ngược lại, khi chúng kế thừa từ các đối tượng khác, tại sao không xem xét chúng đối tượng? Dường như vô nghĩa đối với tôi rằng đứa trẻ của một vật thể không phải là một vật thể ..

Nhân tiện, tôi cũng đã thử nghiệm chúng trong Firefox 22 và có cùng kết quả.

Trả lời

25

Bạn đã bị lừa bởi một cơ chế thường được gọi là "đấm bốc" (c# related article, java related article) khiến cho tất cả mọi người bắt gặp nó. Bạn đã có câu trả lời đúng ngay từ đầu:

Có lẽ vì 1 là nguyên thủy không phải là đối tượng để bắt đầu?

Chính xác như vậy. Tuy nhiên, làm thế nào có thể nguyên thủy bao giờ có thể chứa các phương pháp? Làm thế nào chúng có thể chứa các thuộc tính? Xét cho cùng, trong js, chúng được biểu diễn ở mức thấp nhất có thể (xem #4.3.2). Để thực hiện những giá trị thực sự hữu ích, bất cứ khi nào bạn làm primitive.property, sau đây sẽ xảy ra (#11.2.1):

Object(primitive).property; 

Nói cách khác, js có đấm bốc tự động. Điều này có thể được chứng minh bằng một trong những thủ đoạn yêu thích của tôi:

var primitive = 'food'; 
primitive.isPizza = true; //yummy 
console.log(primitive.isPizza); //undefined. where did my pizza go!? 

primitive.isPizza biến mất vì đấm bốc này:

var primitive = 'food'; 
Object(primitive).isPizza = true; 
console.log(Object(primitive).isPizza); 

Các đóng hộp primitive là bông tuyết độc đáo riêng của mình - khi bạn hộp nó một lần thứ hai, nó không đề cập đến cùng một điều. Các giá trị đóng hộp nhanh chóng GCd và bị lãng quên trong sương mù của thời gian.

này không xảy ra nếu nguyên thủy của bạn không, tốt, một nguyên thủy:

var obj = new String('food'); 
obj.isPizza = true; 
console.log(obj.isPizza); //true 

Điều này có nghĩa là bạn chỉ nên sử dụng các đối tượng, không bao giờ nguyên thủy? Không, vì lý do đơn giản rằng thời gian bạn làm cần phải lưu trữ siêu dữ liệu về nguyên thủy là rất xa và rất ít, và các đối tượng phức tạp điều:

obj === primitive; //false, obj is an object, primitive is a primitive 
+0

Great câu trả lời, cảm ơn. –

+0

Tất cả +1 của tôi đều đến với bạn! – Greg

+0

Myne 2 .... :-). –