LoginSignup
62
43

More than 5 years have passed since last update.

Javascriptにおけるオブジェクトの順序

Last updated at Posted at 2014-12-07

最初のころはObjectの順序は保証されていないと思っていたのでまとめました。

Javascriptエンジン

今回検証する3つのエンジン

v8

  • Node.js
  • Chrome

SpiderMonkey

  • FireFox

Nitoro

  • Safari

結論

v8: Node.js, Chrome

  • Objectの順序
    1. 数値順
    2. 挿入順
  • 1aなど数字から始まる文字は文字列扱い
  • 0は数値扱いで00は文字列扱い

SpiderMonkey: FireFox

  • Objectの基本的な順序
    1. 数値順
    2. 挿入順
  • 最初に挿入される数値が1000以上の場合、挿入順になる
  • 最初に挿入される数値が1000未満の場合、数値順・挿入順になる
  • 1aなど数字から始まる文字は文字列扱い
  • 0は数値扱いで00は文字列扱い

Nitoro: Safari

  • 挿入順

  • ブラウザ間で挙動が異なるので、実用的ではない
  • v8は結構記事書かれてるけど結論出てない感じ 調査中…

検証1

  • Node.js v0.10.33
  • Chrome バージョン 39.0.2171.71
  • FireFox 34.0
  • Safari バージョン 6.0.5...

空オブジェクトに順番に入れてみる

var obj = {};
obj.c = 'c';
obj.b = 'b';
obj.a = 'a';
obj['2'] = '2';
obj[1] = '1';

Node.js

console.log(Object.keys(obj));
// [ '1', '2', 'c', 'b', 'a' ]

console.log(JSON.stringify(obj));
// {"1":"1","2":"2","c":"c","b":"b","a":"a"}

Chrome

console.log(Object.keys(obj));
//  ["1", "2", "c", "b", "a"]

console.log(JSON.stringify(obj));
// {"1":"1","2":"2","c":"c","b":"b","a":"a"}

FireFox

console.log(Object.keys(obj));
// Array [ "1", "2", "c", "b", "a" ]

console.log(JSON.stringify(obj));
// "{"1":"1","2":"2","c":"c","b":"b","a":"a"}"

Safari

console.log(Object.keys(obj));
// ["c", "b", "a", "2", "1"]

console.log(JSON.stringify(obj));
// {"c":"c","b":"b","a":"a","2":"2","1":"1"}

結果

  • safari以外は数値順・挿入順
  • safariは挿入順

検証2

初期値があるとどうなるか

var obj = {
    c: 'c',
    b: 'b',
    a: 'a',
    '3': '3',
    2: 2
};
obj[1] = '1';

Node.js

console.log(Object.keys(obj));
// [ '1', '2', '3', 'c', 'b', 'a' ]

console.log(JSON.stringify(obj));
// {"1":"1","2":2,"3":"3","c":"c","b":"b","a":"a"}

Chrome

console.log(Object.keys(obj));
//  ["1", "2", "3", "c", "b", "a"]

console.log(JSON.stringify(obj));
// {"1":"1","2":2,"3":"3","c":"c","b":"b","a":"a"}

FireFox

console.log(Object.keys(obj));
// Array [ "1", "2", "3", "c", "b", "a" ]

console.log(JSON.stringify(obj));
// "{"1":"1","2":2,"3":"3","c":"c","b":"b","a":"a"}"

Safari

console.log(Object.keys(obj));
// ["c", "b", "a", "3", "2", "1"]

console.log(JSON.stringify(obj));
// {"c":"c","b":"b","a":"a","3":"3","2":2,"1":"1"}

結果

  • safari以外は数値順・挿入順
  • safariは挿入順

検証3

数値が先頭だとどうなるか

var obj = {
    'b': 'b',
    'a': 'a',
    '2c': '2c',
    '1b': '1b',
    '1a': '1a'
};
obj[3] = 3;

Node.js

console.log(Object.keys(obj));
// [ '3', 'b', 'a', '2c', '1b', '1a' ]

console.log(JSON.stringify(obj));
// {"3":3,"b":"b","a":"a","2c":"2c","1b":"1b","1a":"1a"}

Chrome

console.log(Object.keys(obj));
//  ["3", "b", "a", "2c", "1b", "1a"]

console.log(JSON.stringify(obj));
//  {"3":3,"b":"b","a":"a","2c":"2c","1b":"1b","1a":"1a"}

FireFox

console.log(Object.keys(obj));
// Array [ "3", "b", "a", "2c", "1b", "1a" ]

console.log(JSON.stringify(obj));
// "{"3":3,"b":"b","a":"a","2c":"2c","1b":"1b","1a":"1a"}"

Safari

console.log(Object.keys(obj));
// ["b", "a", "2c", "1b", "1a", "3"]

console.log(JSON.stringify(obj));
// {"b":"b","a":"a","2c":"2c","1b":"1b","1a":"1a","3":3}

結果

  • safari以外は数値順・挿入順
  • safariは挿入順
  • 頭数値は文字列扱い

検証4

0とか00とか0絡むとどうなる?

var obj = {
    'b': 'b',
    'a': 'a',
    '01': '01',
    '00': '00',
    '0': '0'
};
obj[1] = 1;

Node.js

console.log(Object.keys(obj));
// [ '0', '1', 'b', 'a', '01', '00' ]

console.log(JSON.stringify(obj));
// {"0":"0","1":1,"b":"b","a":"a","01":"01","00":"00"}

Chrome

console.log(Object.keys(obj));
// ["0", "1", "b", "a", "01", "00"]

console.log(JSON.stringify(obj));
// {"0":"0","1":1,"b":"b","a":"a","01":"01","00":"00"}

FireFox

console.log(Object.keys(obj));
// Array [ "0", "1", "b", "a", "01", "00" ]

console.log(JSON.stringify(obj));
// "{"0":"0","1":1,"b":"b","a":"a","01":"01","00":"00"}"

Safari

console.log(Object.keys(obj));
// ["b", "a", "01", "00", "0", "1"]

console.log(JSON.stringify(obj));
// {"b":"b","a":"a","01":"01","00":"00","0":"0","1":1}

結論

  • safari以外は数値順・挿入順
  • safariは挿入順
  • 0は数値、00は文字列

検証5

階層構造

var obj = {
    a: {
        3: '3',
        2: 2,
        1: '1'
    },
    2: {
        c: 'c',
        1: 1
    }
};
obj[1] = '1';
obj[0] = {};

Node.js

console.log(Object.keys(obj));
// [ '0', '1', '2', 'a' ]

console.log(JSON.stringify(obj));
// {"0":{},"1":"1","2":{"1":1,"c":"c"},"a":{"1":"1","2":2,"3":"3"}}

Chrome

console.log(Object.keys(obj));
//  ["0", "1", "2", "a"]

console.log(JSON.stringify(obj));
//  {"0":{},"1":"1","2":{"1":1,"c":"c"},"a":{"1":"1","2":2,"3":"3"}}

FireFox

console.log(Object.keys(obj));
// Array [ "0", "1", "2", "a" ]

console.log(JSON.stringify(obj));
// "{"0":{},"1":"1","2":{"1":1,"c":"c"},"a":{"1":"1","2":2,"3":"3"}}"

Safari

console.log(Object.keys(obj));
// ["a", "2", "1", "0"]

console.log(JSON.stringify(obj));
// {"a":{"3":"3","2":2,"1":"1"},"2":{"c":"c","1":1},"1":"1","0":{}}

結果

  • safari以外は数値順・挿入順
  • safariは挿入順

検証6

「1000を堺に挙動がかわる」記事を発見したので調査

http://d.hatena.ne.jp/teramako/20140205/p1

var obj = {
    'b': 'b',
    'a': 'a',
    '1000': '1000',
    '999': '999',
    2: '2'
};
obj[1001] = 1001;
obj[998] = 998;

Node.js

console.log(Object.keys(obj));
// [ '2', '998', '999', '1000', '1001', 'b', 'a' ]

console.log(JSON.stringify(obj));
// {"2":"2","998":998,"999":"999","1000":"1000","1001":1001,"b":"b","a":"a"}`

Chrome

console.log(Object.keys(obj));
//  ["2", "998", "999", "1000", "1001", "b", "a"]

console.log(JSON.stringify(obj));
//  {"2":"2","998":998,"999":"999","1000":"1000","1001":1001,"b":"b","a":"a"}

FireFox

console.log(Object.keys(obj));
// Array [ "b", "a", "1000", "999", "2", "1001", "998" ]

console.log(JSON.stringify(obj));
// "{"b":"b","a":"a","1000":"1000","999":"999","2":"2","1001":1001,"998":998}"

Safari

console.log(Object.keys(obj));
// ["b", "a", "1000", "999", "2", "1001", "998"]

console.log(JSON.stringify(obj));
// {"b":"b","a":"a","1000":"1000","999":"999","2":"2","1001":1001,"998":998}

結果

  • Node, Chromeは数値順・挿入順
  • FireFor, Safariは挿入順

検証7

途中から1000を超えるとどうなる? Firefox編

var obj = {
    b: 'b',
    a: 'a',
    999: 999,
    900: 900
};
obj[1] = '1';
obj[1000] = '1000!';
obj[998] = 998;
obj['1002'] = 1002;
obj[1001] = 1001;
obj[0] = 0;

FireFox

console.log(Object.keys(obj));
// Array [ "0", "1", "900", "998", "999", "1000", "1001", "1002", "b", "a" ]

console.log(JSON.stringify(obj));
// "{"0":0,"1":"1","900":900,"998":998,"999":999,"1000":"1000!","1001":1001,"1002":1002,"b":"b","a":"a"}"

結果

  • 数値順・挿入順…

検証8

検証7を全部初期値にすると… FireFox編

var obj = {
    b: 'b',
    a: 'a',
    999: 999,
    900: 900,
    1: 1,
    1000: '1000!',
    998: 998,
    '1002': 1002,
    1001: 1001,
    0: 0
};

FireFox

console.log(Object.keys(obj));
// Array [ "0", "1", "900", "998", "999", "1000", "1001", "1002", "b", "a" ]

console.log(JSON.stringify(obj));
// "{"0":0,"1":"1","900":900,"998":998,"999":999,"1000":"1000!","1001":1001,"1002":1002,"b":"b","a":"a"}"

結果

  • 数値順・挿入順…

検証9

ラスト!! FireFox編

var obj = {
    b: 'b',
    a: 'a',
    1000: '1000!',
    999: 999,
    900: 900,
    1: 1,
    998: 998,
    '1002': 1002,
    1000: 1001,
    0: 0
};

FireFox

console.log(Object.keys(obj));
// Array [ "b", "a", "1000", "999", "900", "1", "998", "1002", "1001", "0" ]
console.log(JSON.stringify(obj));
// "{"b":"b","a":"a","1000":"1000!","999":999,"900":900,"1":1,"998":998,"1002":1002,"1001":1001,"0":0}"

結果

  • 最初に挿入される数値が1000以上だと挿入順になる
62
43
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
62
43