2012-05-02 47 views
8

Tôi đang gặp một hành vi kỳ quặc (có thể nó không phải là lạ chút nào nhưng chỉ tôi không hiểu tại sao) với một mảng javascript chứa một số đối tượng.Mảng Javascript trở thành một cấu trúc đối tượng

Vì tôi không có chuyên gia javascript, có thể giải thích rõ ràng là tại sao điều này xảy ra, tôi không biết điều đó.

Tôi có javascript đang chạy trong tài liệu. Nó làm cho một mảng của các đối tượng tương tự như sau:

var myArray = [{"Id":"guid1","Name":"name1"},{"Id":"guid2","Name":"name2"},...]; 

Nếu tôi in ra mảng này tại nơi nó được tạo ra như JSON.stringify (myArray), tôi nhận được những gì tôi đã mong đợi:

[{"Id":"guid1","Name":"name1"},{"Id":"guid2","Name":"name2"},...] 

Tuy nhiên, nếu tôi cố gắng truy cập mảng này từ một tài liệu con cho tài liệu này (một tài liệu trong một cửa sổ được mở bởi tài liệu đầu tiên) thì mảng đó không còn là mảng nữa. Vì vậy, làm JSON.stringify (parent.opener.myArray) trong tài liệu đứa trẻ sẽ dẫn đến việc sau đây:

{"0":{"Id":"guid1","Name":"name1"},"1":{"Id":"guid2","Name":"name2"},...} 

Và đây không phải là những gì tôi đã mong đợi - Tôi đã chờ đợi để có được giống như tôi đã làm trong tài liệu gốc.

Bất cứ ai có thể giải thích cho tôi tại sao điều này xảy ra và cách khắc phục để mảng vẫn là một mảng khi được giải quyết từ cửa sổ/tài liệu con?

PS. các đối tượng không được thêm vào mảng như đã nêu ở trên, chúng được thêm như sau:

function objTemp() 
{ 
    this.Id = ''; 
    this.Name = ''; 
}; 

var myArray = []; 

var obj = new ObjTemp(); 
obj.Id = 'guid1'; 
obj.Name = 'name1'; 

myArray[myArray.length] = obj; 

Nếu có sự khác biệt nào.

Bất kỳ trợ giúp sẽ được nhiều đánh giá cao, cả hai để sửa chữa vấn đề của tôi mà còn để hiểu rõ hơn những gì đang xảy ra :)

+0

Tôi không thể sao chép. Bạn đã kiểm tra trình duyệt nào? Bạn đã sử dụng thư viện JSON chưa? – Bergi

+0

Tôi đang thử nghiệm trong IE vì đó là yêu cầu. Cá nhân tôi sẽ không chọn IE nhưng nó không phải là tùy thuộc vào tôi. Tôi chỉ sử dụng json trong ví dụ này để xâu chuỗi cảnh báo của tôi. Tôi không sử dụng bất kỳ thư viện json nào cho mã tạo ra hành vi. – Aidal

+0

Xin chào, cảm ơn vì đã chấp nhận. Vui mừng khi biết cách giải quyết của tôi tỏ ra hữu ích. Happy coding :) + 1 cho câu hỏi của bạn BTW. Tôi đã học được từ nó, quá –

Trả lời

6

Dòng cuối cùng có thể gây ra vấn đề, bạn đã cố gắng thay thế myArray[myArray.length] = obj; với myArray.push(obj);? Có thể là, vì bạn đang tạo một chỉ mục mới một cách rõ ràng, Mảng được biến thành một đối tượng ... mặc dù tôi chỉ đoán ở đây. Bạn có thể thêm mã được sử dụng bởi tài liệu con truy xuất myArray không?

Sửa

Bỏ qua ở trên, vì nó sẽ không thực hiện bất kỳ sự khác biệt. Mặc dù, không muốn khoe khoang, tôi vẫn đang suy nghĩ đúng đường. Ý tưởng của tôi là, bằng cách chỉ sử dụng các phương thức mảng độc quyền, trình thông dịch sẽ thấy đó là các đầu mối về loại myArray. Vấn đề là: myArray một mảng, như xa như tài liệu gốc có liên quan, nhưng kể từ khi bạn đang đi qua các mảng từ một tài liệu khác, đây là những gì sẽ xảy ra:

Một mảng là một đối tượng, hoàn chỉnh với đó là nguyên mẫu và phương pháp riêng. Bằng cách chuyển nó tới một tài liệu khác, bạn đang truyền toàn bộ đối tượng Array (giá trị và nguyên mẫu) làm một đối tượng cho tài liệu con. Khi chuyển biến giữa các tài liệu, bạn đang tạo một bản sao của biến đó một cách hiệu quả (chỉ có thời gian JavaScript sao chép các giá trị của một biến). Vì một mảng là một đối tượng, tất cả các thuộc tính của nó (và các phương thức/thuộc tính nguyên mẫu) được sao chép vào một thể hiện 'vô danh' của đối tượng Object. Đã xảy ra sự cố dọc theo dòng var copy = new Object(toCopy.constructor(toCopy.valueOf())); ...cách dễ nhất xung quanh này, IMO, là nghiêm ngặt các mảng withing bối cảnh cha mẹ, bởi vì ở đó, người phiên dịch biết nó là một mảng:

//parent document 
function getTheArray(){ return JSON.stringify(myArray);} 
//child document: 
myArray = JSON.parse(parent.getTheArray()); 

Trong ví dụ này, var được chuyển đổi thành chuỗi trong bối cảnh mà vẫn đối xử với myArray như một mảng JavaScript thực, do đó chuỗi kết quả sẽ là những gì bạn mong đợi. Khi chuyển chuỗi được mã hóa JSON từ tài liệu này sang tài liệu khác, chuỗi này sẽ không thay đổi và do đó, JSON.parse() sẽ cung cấp cho bạn bản sao chính xác của biến số myArray.

Lưu ý rằng đây chỉ là một cú đâm hoang dã khác trong bóng tối, nhưng bây giờ tôi đã suy nghĩ thêm một chút. Nếu tôi sai về điều này, hãy sửa tôi ... Tôi luôn sẵn lòng học hỏi. Nếu điều này hóa ra là đúng, hãy cho tôi biết, vì điều này chắc chắn sẽ chứng minh một cạm bẫy cho tôi sớm hay muộn

+0

Không, cú pháp đó là hoàn toàn hợp lệ để tạo thành viên mới của một mảng. Mặc dù .push() là mô tả hơn (và tôi thích nó tốt hơn), nhiệm vụ cũng hoạt động và thậm chí còn nhanh hơn một chút. – Bergi

+0

Tôi không nghĩ rằng mảng không hợp lệ do cách tôi thêm các mục vào nó, như tôi cũng đã nêu trong bài đăng, nếu tôi cố gắng cảnh báo mảng được xâu chuỗi có vẻ chính xác (còn gọi nó không phải là đối tượng mà là mảng) . Nếu tôi làm chính xác điều tương tự từ tài liệu con, mảng bây giờ là một đối tượng, không chỉ khi tôi cảnh báo var được xâu chuỗi nhưng mã được cho là hoạt động với mảng sẽ ném một lỗi vì ví dụ: myArray [0] .Id là null (vì nó không tồn tại nguyên nhân). – Aidal

+0

Xâu chuỗi mảng trên trang gốc và sau đó phân tích cú pháp chuỗi trên trang con đã thực hiện mẹo và nhờ câu trả lời khá kỹ lưỡng, tôi cũng đã học được điều gì đó :) – Aidal

1

Hãy xem kết thúc của bài viết này http://www.karmagination.com/blog/2009/07/29/javascript-kung-fu-object-array-and-literals/ để biết ví dụ về hành vi và giải thích này.

Về cơ bản, nó xuất hiện dưới dạng Array là một kiểu gốc và mỗi khung có tập hợp riêng của người bản xứ và các biến.

Từ bài viết:

// in parent window 
var a = []; 
var b = {}; 
//inside the iframe 
console.log(parent.window.a); // returns array 
console.log(parent.window.b); // returns object 

alert(parent.window.a instanceof Array); // false 
alert(parent.window.b instanceof Object); // false 
alert(parent.window.a.constructor === Array); // false 
alert(parent.window.b.constructor === Object); // false 

Cuộc gọi của bạn để JSON.stringify thực sự thực hiện việc kiểm tra sau (từ nguồn json.js), mà dường như được thất bại trong việc xác định nó như một mảng:

 // Is the value an array? 
     if (Object.prototype.toString.apply(value) === '[object Array]') { 
      //stringify 
+1

Na, có vẻ như chính xác không sử dụng Array.isArray, mà sẽ làm việc qua cửa sổ, thay vào đó nó sẽ sử dụng instanceof để gây ra hành vi mô tả. – Bergi

+0

Ồ, có vẻ như đây là trình duyệt cụ thể vì json2.js mặc định chỉ thực thi phiên bản gốc của trình duyệt của stringify nếu có sẵn (và nó phải nằm trong tất cả các trình duyệt hiện đại) – nvuono

+0

Tôi có nghĩa là mã 'Object.prototype.toString .apply (value) === '[object Array]' 'sẽ * không * thất bại, mặc dù bạn nói vậy. – Bergi

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