行動すれば次の現実

ほどよくモダンなシステム開発を目指しています。メインテーマは生産性、Ruby、Javascriptです。

RubyとJavascriptにおける連想配列の順序保証の違い

RubyとJavascriptでは連想配列(Rubyの場合はHash、Javascriptの場合はオブジェクトリテラル)の順序保証が異なります。

最近はバックエンドでRuby、フロントエンドはJavascriptの構成にして開発するケースが増えています。

RubyでAPIの結果を連想配列で返し、Javascript側で連想配列をeachして順番に処理を行う場合は、そのギャップに注意が必要です。

Rubyの場合はHashの順序が保証される

Ruby(v1.9以降)の場合、Hashの順序が保証されます。

hash = { '1':'one', '2':'two', '4':'four', '3':'three' }
p hash
=>  {:"1"=>"one", :"2"=>"two", :"4"=>"four", :"3"=>"three"}

hash.each do |k, v|
  p v
end

=> "one"
=> "two"
=> "four"
=> "three"

Javascriptの場合はオブジェクトリテラルの順序が保証されない

Javascriptの場合、オブジェクトリテラルの順序が保証されません。

const hash = { 1:'one', 2:'two', 4:'four', 3:'three' }
console.log(hash)
=> {1: 'one', 2: 'two', 3: 'three', 4: 'four'}

Object.values(hash).forEach((value) => {
  console.log(value)
});
=> "one"
=> "two"
=> "three"
=> "four"

そのため、Javascriptで順序を保ちたい場合は、順序を管理するための配列を別途用意する必要があります。

const hash = {
  entities:  { 1:'one', 2:'two', 4:'four', 3:'three’ },
  orders: [1 ,2 ,4 ,3]
}

hash.orders.forEach((k) => {
  const value = hash.entities[k];
  console.log(value)
});
=> "one"
=> "two"
=> "four"
=> "three"