2012-02-07 12 views
6

配列オブジェクトとして宣言された配列のようなオブジェクトをストリングしようとしましたが、JSON.stringifyが配列のようなオブジェクトを正しく処理していないことがわかりました配列オブジェクト。Javascript Arrayオブジェクトと配列類似オブジェクト - 明確化

は、より明確にするため、以下を参照してください - >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 [] 

それはうまく働いたと私はvar simpleArray = {};

var simpleArray = [];を変更したときに私{"test1":"test 1","test2":"test 2"}を返しました。

誰かが私がもっと読むことができるいくつかの光を照らすことができますか?

編集:

質問:JSON.stringifyは両方のケースで{"test1":"test 1","test2":"test 2"}を返すことができなかった理由のtypeof simpleArray = []simpleArray = {}返されたオブジェクト、?

答えて

2

配列を必要としません。 JavaScriptで「連想配列」が必要な場合は、実際にはオブジェクトが必要です。{}

あなたはinstanceof Arrayでそれらを区別することができます。

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

はEDIT:それはそれを処理することができます。配列のすべての要素を直列化します。しかし、要素であるためには、数字キーが必要です。この場合、何もありません。

これはJSON固有のものではありません。それはtoSourcelengthプロパティと一貫しています。

+0

私が知りたいのは、JSON.stringifyが[]として宣言されたときに処理できなかった理由です。 –

+0

ありがとうございました!私はinstanceofを探していた。私はどちらの場合でもオブジェクトを返すtypeofを使用しようとしていました。 –

+1

ES 5以降では、フレームセーフである 'Array.isArray(...)'(15.4.3.2)もあります。エミュレートすることができます。 – PointedEars

4

違いはインデックスです。配列[]を使用すると、インデックスは正の整数にしかなりません。

だから、次は間違っている:

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

test1test2は整数ではありませんので。

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

またはあなたはjavascriptオブジェクトを宣言した場合、その後の特性は任意の文字列を指定できます:

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

と同等です:

それを修正するためには、整数ベースのインデックスを使用する必要があります
var array = { }; 
array.test1 = 'test 1'; 
array.test2 = 'test 2'; 
+0

だから、 'var simpleArray = [];を実行するとどうなりますか? simpleArray ['test2'] = 'テスト2'; '? –

+3

@MattFenwick、何が起こるかは、あなたが期待するものとは逆です: 'simpleArray.length = 0'は、この配列に要素がないことを意味します。 'simpleArray.test2'を使って、定義したプロパティにアクセスすることができます。それは回避すべきコードを混乱させるだけです。 –

+0

+1詳細な説明がありますが、私が知りたいのは、JSON.stringifyが[]として宣言されたときに処理できなかった理由です。私はtypeofを使用しようとし、それは両方の場合に私のオブジェクトを返しました。私はこれを私の質問に加えるつもりです。 –

1

JSON.stringifyが配列を検出すると、同様の方法で0からsimpleArray.lengthへのループを反復して値を検索します。例:

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

したがって、プロパティの設定はJSONでは完全に見えません。

{}でオブジェクトを定義すると、JSONはオブジェクトをオブジェクトとして扱うため、オブジェクトのプロパティ(プロトタイプチェーンから継承されたプロパティを除く)をループします。この方法では、test1test2のプロパティが見つかり、正常に返されます。

2

「誰かが私がもっと読むことができる、いくつかの参考文献や参考文献を出すことはできますか?」あなたはJSONデータを扱っているとき

は、あなたが仕様書の要​​件について読むためにjson.orgを参照することができます。

では、Arrayは、,で区切られた値の順序リストです。

enter image description here

のでJSON.stringify()は単に、単純な順序付けられたリストとして表現することができなかったものを無視しています。

あなたが行うのであれば...

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

...あなたはまだ配列を与えているので、それは数字のみインデックスを期待して、何か他のものを無視しています。

JSONは言語に依存しないため、JSONを使用する方法では、どの言語構造が各JSON構造に最も適しているかを判断する必要があります。

だから、JSONはあなたがJavaScriptオブジェクトと配列と非常によく似ていますが、彼らは厳密には同じじゃないことに注意する必要があります

{} // object 
[] // array 

...以下の構成を有します。

構造を作成するために使用される構造体は、JSON構造体が許容するものに適合しなければなりません。このため、非数値プロパティはが削除され、が除外されています。

JavaScriptは気にしませんが、JSONはそれらを許容しません。

+0

非数値プロパティ(より良い:非数値*名前*のプロパティ)は削除されません。彼らは最初の反復のために考慮されていません。 – PointedEars

+0

@PointedEars:言葉が貧弱でした。 *「やあ、彼らは私のArrayオブジェクトにはありますが、私のJSONテキストにはありません!」のように、開発者の視点として取り除かれました。私は* "除外"と言っていたはずです*。 –

-1

あなたのコードは意味的に正しいわけではありませんが、ほとんどのJavaScriptエンジンはプログラマーにとって本当にいいですから、これらのタイプのエラーはです。

簡単なテストケース:

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

これが原因で、まだArrayようaを扱うJSON.stringifyにおけるいくつかの厳しさであるかもしれません。 私はあまりそれを心配しません。これは、エラーであるため、プログラムで発生してはならない状況です。 JSLintは、これらの問題や潜在的な多くの問題をコードで捕らえるための一般的なツールです。

+0

Pray tell、*構文*に間違いがありますか? – PointedEars

+0

私はそれがむしろ明らかだと思った: 'Array'sで文字列キーを宣言することはできません。ほとんどのJavaScriptエンジンがそれを受け入れるだけで、それは_correct_になりません。私はあなたが下位投票がそれに値すると思ったことを願っています。 – Halcyon

+0

JavaScriptの性質、ECMAScriptオブジェクトの性質、プログラミング言語の構文に属するものについては、深刻な誤解があります。 1つのコメントはそれを短くすることです。 *キーはありません。*オブジェクトには名前付きのプロパティ*があります。プロパティ名は '' '' ''、 '.'または暗黙的に(スコープチェイン)アクセスされる*文字列*です。 JavaScriptはECMAScript実装です。 * JavaScript *には、SpiderMonkeyとRhinoの2つのプロダクション品質 "実装"しかありません。 JScriptのようなものは* ECMAScript *の実装です。続ける... – PointedEars

0

Javascriptでは、すべてがオブジェクトなので、配列さえあります。

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

配列はオブジェクトと同じように格納されます これは、あなたが得る理由です。実際、配列はハッシュテーブルオブジェクトだけです。たとえば、アクセスしたときに指定したインデックス。

>> l[0] 

はオフセットとして解釈されませんが、ハッシュされてから検索されます。

だから、配列はオブジェクト(いくつかの組み込み配列メソッドあり)であるため、オブジェクトのように扱い、特定のキーの下に値を置くことができます。 しかし、数字で索引付けされたキーだけが長さの計算に使用されます。

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

読むArray - MDN詳しく 、あなたがこれを行うべきではない理由をAssociative Arrays considered harmfulため。

+0

*すべて*はオブジェクトではありません。プリミティブな値があります。しかし、 "Javascript"はありません。いくつかの異なるECMAScript実装があります。 – PointedEars

1

Arrayインスタンスと他のオブジェクトの違いは、ECMAScript Language Specification, Edition 5.1の15.4節で指定されています。

あなたはすべてオブジェクト参照とブラケットプロパティアクセサ構文を使用することができますしながら、ということがわかります -

objRef[propertyName] 

からArrayインスタンスは特別です。 2 -1より小さい符号なし32ビット整数値の文字列表現のみがカプセル化された配列構造の要素にアクセスし、書き込みアクセスはArrayインスタンスのlengthプロパティの値に影響します。

15.12節は、JSONオブジェクトとそれに対応するstringifyメソッドを指定しています。

関連する問題