2012-02-07 45 views
6

Tôi đã cố gắng xâu chuỗi một đối tượng giống như mảng được khai báo là đối tượng mảng và nhận thấy JSON.stringify không xử lý chính xác đối tượng giống mảng khi nó được định nghĩa là mảng đối tượng.Đối tượng mảng JavaScript vs mảng giống như đối tượng - Làm rõ

Xem dưới đây cho rõ ràng hơn, ->jsFiddle

var simpleArray = []; //note that it is defined as Array Object 

alert(typeof simpleArray); // returns object -> Array Object 

simpleArray ['test1'] = 'test 1'; 
simpleArray ['test2'] = 'test 2'; 

alert(JSON.stringify(simpleArray)); //returns [] 

Nó hoạt động tốt và trở về tôi {"test1":"test 1","test2":"test 2"} khi tôi thay đổi

var simpleArray = [];-var simpleArray = {};.

Ai đó có thể làm sáng tỏ hoặc tham khảo một số nơi tôi có thể đọc thêm?

Edit:

Câu hỏi: Khi typeof simpleArray = []simpleArray = {} trở đối tượng, tại sao JSON.stringify đã không thể trở {"test1":"test 1","test2":"test 2"} trong cả hai trường hợp?

Trả lời

2

Bạn không muốn mảng. Khi bạn muốn có một "mảng kết hợp" trong JavaScript, bạn thực sự muốn một đối tượng, {}.

Bạn có thể phân biệt chúng với instanceof Array:

[] instanceof Array // true 
({}) instanceof Array // false 

EDIT: nó có thể xử lý nó. Nó tuần tự hóa tất cả các phần tử của mảng. Tuy nhiên, để trở thành một phần tử, phải có một phím số. Trong trường hợp này, không có.

Điều này không có gì độc đáo đối với JSON. Nó phù hợp với toSource và thuộc tính length.

+0

Tôi hiểu rằng một phần, những gì tôi muốn biết là tại sao JSON.stringify không thể xử lý khi được khai báo là []. –

+0

Cảm ơn bạn !. Tôi đang tìm kiếm instanceof. Tôi đã cố gắng sử dụng typeof đã trở về đối tượng trong cả hai trường hợp. –

+1

Vì ES 5 cũng có 'Array.isArray (...)' (15.4.3.2) mà ngược lại là khung an toàn. Nó có thể được mô phỏng. – PointedEars

4

Sự khác biệt là các chỉ mục. Khi bạn sử dụng mảng [], các chỉ mục chỉ có thể là số nguyên dương.

Vì vậy, sau đây là sai:

var array = [ ]; 
array['test1'] = 'test 1'; 
array['test2'] = 'test 2'; 

test1test2 không số nguyên. Để khắc phục nó, bạn cần phải sử dụng số nguyên chỉ số dựa trên:

var array = [ ]; 
array[0] = 'test 1'; 
array[1] = 'test 2'; 

hoặc nếu bạn khai báo một đối tượng javascript sau đó các thuộc tính có thể được bất kỳ chuỗi:

var array = { }; 
array['test1'] = 'test 1'; 
array['test2'] = 'test 2'; 

tương đương với:

var array = { }; 
array.test1 = 'test 1'; 
array.test2 = 'test 2'; 
+0

Vì vậy, điều xảy ra khi bạn thực hiện 'var simpleArray = []; simpleArray ['test2'] = 'test 2'; '? –

+3

@MattFenwick, điều xảy ra là trái với những gì bạn có thể mong đợi: 'simpleArray.length = 0' có nghĩa là không có phần tử nào trong mảng này. Bạn vẫn có thể sử dụng 'simpleArray.test2' để truy cập thuộc tính mà bạn đã định nghĩa. Nó chỉ là mã khó hiểu mà nên tránh. –

+0

+1 cho giải thích chi tiết nhưng, điều tôi muốn biết là tại sao JSON.stringify không thể xử lý khi được khai báo là []. Tôi đã cố gắng sử dụng typeof và nó trả về cho tôi đối tượng trong cả hai trường hợp. Tôi sẽ thêm điều này vào câu hỏi của tôi. –

1

Khi JSON.stringify gặp một mảng, nó lặp lại theo cách tương tự với vòng lặp for từ 0 đến simpleArray.length để tìm giá trị. Ví dụ:

var a = []; 
a[5] = "abc"; 
alert(JSON.stringify(a)); // alerts [null,null,null,null,null,"abc"] 

Do đó, việc đặt thuộc tính trên nó sẽ hoàn toàn ẩn đối với JSON.

Tuy nhiên xác định đối tượng với {} làm cho JSON coi nó là đối tượng và do đó nó lặp lại thuộc tính của đối tượng (không bao gồm thuộc tính được thừa kế từ chuỗi mẫu). Theo cách này, bạn có thể tìm thấy các thuộc tính test1test2 của mình và trả lại thành công những gì bạn mong đợi.

2

"Ai đó có thể làm sáng tỏ hoặc tham khảo một số nơi tôi có thể đọc thêm?"

Khi bạn đang làm việc với JSON dữ liệu, bạn có thể tham khảo json.org để đọc về các yêu cầu của đặc tả.

Trong JSON, một Array là danh sách đơn hàng của các giá trị được phân tách bằng ,.

enter image description here

Vì vậy, các JSON.stringify() chỉ đơn giản là bỏ qua bất cứ điều gì mà không thể được biểu diễn dưới dạng một danh sách lệnh đơn giản.

Vì vậy, nếu bạn làm ...

var simpleArray = []; 
simpleArray.foo = 'bar'; 

... bạn vẫn đưa ra một mảng, vì vậy nó được kỳ vọng chỉ số chỉ số, và bỏ qua bất cứ điều gì khác.

JSON là ngôn ngữ độc lập, các phương pháp để làm việc với JSON cần đưa ra quyết định về cấu trúc ngôn ngữ nào phù hợp nhất cho mỗi cấu trúc JSON.

Vì vậy, JSON có cấu trúc sau ...

{} // object 
[] // array 

Bạn nên lưu ý rằng mặc dù giao diện rất giống với JavaScript đối tượng và mảng, họ không đúng như vậy.

Mọi cấu trúc JavaScript được sử dụng để tạo cấu trúc JSON phải phù hợp với cấu trúc JSON sẽ cho phép. Đây là lý do tại sao các thuộc tính không phải là số được xóa .

Trong khi JavaScript không quan tâm đến chúng, JSON sẽ không dung thứ cho chúng.

+0

Thuộc tính không phải số (tốt hơn: các thuộc tính có tên * không *) không bị xóa.Chúng không được xem xét cho việc lặp lại ngay từ đầu. – PointedEars

+0

@PointedEars: Đó là từ ngữ nghèo nàn. Tôi có nghĩa là loại bỏ như là một vấn đề của quan điểm của nhà phát triển, như trong * "Này, họ đang ở trong đối tượng mảng của tôi, nhưng không phải trong văn bản JSON của tôi!" *. Tôi nên nói * "loại trừ" *. –

-1

Mã của bạn không đúng ngữ nghĩa, nhưng vì hầu hết các công cụ JavaScript đều thực sự tốt trên lập trình viên, chúng cho phép các loại lỗi này.

Một kiểm tra trường hợp nhanh chóng:

var a = []; 
a.b = "c"; 
console.log(JSON.stringify(a));//yields [], and not {"b":"c"} as you might expect 

Điều này có thể vì một số tính nghiêm minh trong JSON.stringify mà vẫn đối xử với a như một Array. Tôi sẽ không lo lắng quá nhiều. Đây là một tình huống không nên xảy ra trong chương trình của bạn vì nó là một lỗi. JSLint là một công cụ phổ biến để nắm bắt những vấn đề này và nhiều tiềm năng khác trong mã của bạn.

+0

Hãy cầu nguyện cho biết, có gì sai với cú pháp *? – PointedEars

+0

Tôi nghĩ nó khá rõ ràng: bạn không thể khai báo các chuỗi ký tự trong 'Array'. Chỉ vì hầu hết các công cụ JavaScript chấp nhận nó không làm cho nó _correct_. Tôi hy vọng bạn nghĩ rằng bỏ phiếu xuống là giá trị nó. – Halcyon

+0

Bạn có quan niệm sai lầm nghiêm trọng về bản chất của JavaScript, đối tượng ECMAScript và những gì thuộc về cú pháp của ngôn ngữ lập trình. Một bình luận là viết tắt cho điều đó. * Không có phím. * Đối tượng có * thuộc tính * với tên. Tên thuộc tính là * strings *, được truy cập với '['… ']', '.', hoặc ngầm (chuỗi phạm vi). JavaScript là một triển khai ECMAScript. * JavaScript * chỉ có hai "triển khai" chất lượng sản xuất: SpiderMonkey và Rhino; những người khác như JScript là * triển khai ECMAScript *. Để được tiếp tục… – PointedEars

0

Trong Javascript, mọi thứ đều là một đối tượng, vì vậy ngay cả Mảng. Đây là lý do bạn nhận được:

>> var l = [1, 2]; 
>> typeof l 
"object" 

Mảng được lưu trữ giống như đối tượng. Vì vậy, trên thực tế, mảng chỉ là các đối tượng có thể bắt đầu. Chỉ mục bạn cung cấp khi truy cập ví dụ:

>> l[0] 

không được hiểu là bù trừ, nhưng được băm và sau đó tìm kiếm. Vì vậy, các mảng, chỉ là các đối tượng (với một số phương thức mảng dựng sẵn) và do đó bạn có thể xử lý chúng như các đối tượng và đặt một giá trị theo một khóa nhất định nào đó. Nhưng chỉ những khóa được lập chỉ mục theo số được sử dụng để tính toán độ dài.

>> var l = [] 
>> l.length 
0 
>> l[5] = 1; 
>> l.length 
6 
>> l 
[undefined, undefined, undefined, undefined, undefined, 1] 
>> l.hello = "Hello" 
>> l.length 
6 

đọc Array - MDN để biết thêm thông tin và Associative Arrays considered harmful lý do tại sao bạn không nên làm điều này.

+0

Không * mọi thứ * là một đối tượng. Có những giá trị nguyên thủy. Nhưng không có "Javascript", có một số triển khai ECMAScript khác nhau. – PointedEars

1

Sự khác biệt giữa Array trường hợp và các đối tượng khác được chỉ định trong ECMAScript Language Specification, Edition 5.1, phần 15.4.

Bạn sẽ tìm thấy ở đó trong khi bạn có thể sử dụng khung cú pháp accessor tài sản với tất cả các tài liệu tham khảo đối tượng -

objRef[propertyName] 

- Array trường hợp thật đặc biệt. Chỉ sử dụng giá trị tham số mà biểu diễn chuỗi là giá trị số nguyên 32 bit chưa ký được ít hơn 2 -1 truy cập phần tử của cấu trúc mảng đóng gói và quyền ghi sẽ ảnh hưởng đến giá trị của thuộc tính length của cá thể Array.

Mục 15.12 chỉ định đối tượng JSON và phương pháp stringify tương ứng.

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