StackOverflow 上有个问题
JavaScript 是否保证对象属性顺序?
简而言之,答案是否定的,它没有。因此,当将 PHP 数组转换为 Javascript 对象时,不会保留键顺序。
PHP 和 Javascript 中的数组之间的主要区别在于后者只能保存从零开始的连续整数键。因此,并非总是可以将 PHP 数组转换为 Javascript 数组。让我们看几个例子:
// example 1
echo json_encode(array(0 => 'a', 1 => 'b')) // outputs ["a","b"]
// example 2
echo json_encode(array(0 => 'a', 3 => 'b')) // outputs {"0":"a","3":"b"}
// example 3
echo json_encode(array(3 => 'b', 0 => 'a')) // outputs {"3":"b","0":"a"}, but in Javascript the key order will be the same as in example 2
- 在第一个示例中,
json_encode
将 PHP 数组转换为相同的 Javascript 数组。
- 在第二个示例中,它转换为对象,因为键顺序不是顺序的。
- 在第三个示例中,它也转换为对象。但是在 Javascript 中,对象 2 和 3 将是相同的,具有相同的键顺序,即使键以不同的顺序列出。因此
json_encode
,不保留键顺序的不是函数,而是 Javascript 本身。
回到我们的问题:如何将 PHP 数组传递给 Javascript 并保留键顺序?一种方法是将 PHP 键值对包装到数组中:
// original array:
array(
3 => 'b',
0 => 'a'
)
// must be converted to:
array(
array(3, 'b'),
array(0, 'a')
)
然后json_encode
将产生以下 Javascript 数组:
[
[3,"b"],
[0,"a"]
]
最后一部分是在 Javascript 中遍历这样的数组:
var php_encoded_array = [
[3,"b"],
[0,"a"]
];
for (var i=0; i < php_encoded_array.length; i++) {
var rec = php_encoded_array[i],
key = rec[0],
value = rec[1];
console.log(key + ': ' + value);
}
// It will output:
// 3: b
// 0: a
// Which is the exact same order as in the PHP array
这种方法也与非整数键兼容。
这是用于在 PHP 端转换数组的代码(由pr1001在类似问题中建议)。它适用于一维数组。
array_map(
function($key, $value) { return array($key, $value); },
array_keys($data),
array_values($data)
)
这是多维数组的递归函数实现:
function array_preserve_js_order(array $data) {
return array_map(
function($key, $value) {
if (is_array($value)) {
$value = array_preserve_js_order($value);
}
return array($key, $value);
},
array_keys($data),
array_values($data)
);
}