配列の添字が大きくなりすぎると
- カテゴリ:
- JavaScript
- PHP
- コメント数:
- Comments: 0
◆ 添字が数値型で大きくなりすぎるとちゃんと保存されないので文字列にしたほうがいい
◆ 全く同じキーでは取り出せる値は一緒だけど 近い数値のキーで上書きしたら他のも書き換わる可能性があるのでやらないほうが安全
◆ 全く同じキーでは取り出せる値は一緒だけど 近い数値のキーで上書きしたら他のも書き換わる可能性があるのでやらないほうが安全
配列の添字が大きくなると問題が出てきます
原因は添字部分を一度評価するからです
-0 を添字に出来ないのも一度評価が挟まれるからです
もっと大きくなると
関係ないキーでデータが取り出せても 保存したときのキーで同じ値が取り出せるんだったら問題ないよ って思うかもしれないですが 複数の添字に対してデータ保存したときに内部のデータでは添字が一緒になってしまって最後に保存したもので上書きされる可能性があります
オブジェクトの場合でも同じ現象が起きます
大きい数値が添字やキーになる場合は toString を通すと良さそうです
なので文字列化します
PHP はよく謎の変換をするので 数値に変換可能な文字列を添え字にすると数値化されてしまわないか心配でしたが問題なかったです
JavaScriptの場合
こういうことがおきます> var a = []
< undefined
> a[1234567890234567890] = 10
< 10
> a[1234567890234567890]
< 10
> a[1234567890234567891]
< 10
> a[1234567890234568000]
< 10
入れたときと同じ添字なら同じ値は返って来ますが別の値でもデータが取り出せてしまいます< undefined
> a[1234567890234567890] = 10
< 10
> a[1234567890234567890]
< 10
> a[1234567890234567891]
< 10
> a[1234567890234568000]
< 10
原因は添字部分を一度評価するからです
-0 を添字に出来ないのも一度評価が挟まれるからです
> 12345678901234567890
< 12345678901234567000
値が大きいとこのように別の数値になってしまいます< 12345678901234567000
もっと大きくなると
> a[12345678901234567890123467890] = 999
< 999
> a["1.2345678901234568e+28"]
< 999
こうなります< 999
> a["1.2345678901234568e+28"]
< 999
関係ないキーでデータが取り出せても 保存したときのキーで同じ値が取り出せるんだったら問題ないよ って思うかもしれないですが 複数の添字に対してデータ保存したときに内部のデータでは添字が一緒になってしまって最後に保存したもので上書きされる可能性があります
オブジェクトの場合でも同じ現象が起きます
> o = {}
> o[12345678901238901234890] = 123
< 123
> o["1.23456789012389e+22"]
< 123
大丈夫そうなオブジェクトのリテラルでも> o[12345678901238901234890] = 123
< 123
> o["1.23456789012389e+22"]
< 123
> var o = {123123123123123123123123123123:123}
> o
< Object {1.2312312312312312e+29: 123}
こうなってしまっています> o
< Object {1.2312312312312312e+29: 123}
対策
文字列にするだけで解決できます> var a = []
< undefined
> a["123456789012345678901234567890"] = 100
< 100
> Object.keys(a)
< ["123456789012345678901234567890"]
> var o = {"123123123123123123123123123123":123}
< undefined
> o
< Object {123123123123123123123123123123: 123}
< undefined
> a["123456789012345678901234567890"] = 100
< 100
> Object.keys(a)
< ["123456789012345678901234567890"]
> var o = {"123123123123123123123123123123":123}
< undefined
> o
< Object {123123123123123123123123123123: 123}
大きい数値が添字やキーになる場合は toString を通すと良さそうです
PHPの場合
PHPでも一緒です>>> $a[12345678901234567890] = 1
=> 1
>>> $a[12345678901234567890]
=> 1
>>> $a[12345678901234567800]
>>> array_keys($a)
=> [
-350287872,
]
=> 1
>>> $a[12345678901234567890]
=> 1
>>> $a[12345678901234567800]
>>> array_keys($a)
=> [
-350287872,
]
なので文字列化します
>>> $a["123456789012345678901234567890"] = 111
=> 111
>>> array_keys($a)
=> [
"123456789012345678901234567890",
]
=> 111
>>> array_keys($a)
=> [
"123456789012345678901234567890",
]
PHP はよく謎の変換をするので 数値に変換可能な文字列を添え字にすると数値化されてしまわないか心配でしたが問題なかったです