为什么js的"关联数组"不能转成json字符串而对象可以?

定义这么一个js的“关联数组”:

var arr = new Array();
    arr['school'] = 1;
    arr['team'] = 2;
    alert(JSON.stringify(arr));

得到的结果如图:
图片描述

为什么会这样?实在不知道为什么了,但是通过:

alert(arr.school);

这种方法可以取到值,这样看是存在的,但是好像又不存在,实在搞不懂
用对象的方式就正常转换:

var obj = {
    school: 1,
    team : 2
}
alert(JSON.stringify(obj));

如果说js不支持这种关联数组的形式但为什么可以取值呢?能取到值但为什么转成json字符串就什么也没有了呢?

阅读 4.8k
5 个回答

一句话,你的 arr 是有两个属性的空数组,数组转字符串当然是展示数组的内容,不会去遍历数组的属性!下面解释:

js不支持这种关联数组的形式但为什么可以取值呢?

因为数组本身也是对象,特殊的对象,

var arr = new Array();
    arr['school'] = 1;
    arr['team'] = 2;

从对象的角度来看,你只是给 arr 对象增加了两个属性,那么你取值,实际上是读取属性,当然是可以取到的的;你给 arr 增加值了么?没有!这个地方,arr 的 length 还是 0 ,也就是说,arr 还是 [] 空数组,那么你用 JSON.stringify() 显示的当然是 []

clipboard.png

能取到值但为什么转成json字符串就什么也没有了呢?

能取到值是因为你取的是属性,数组作为对象,当然可以设置读取属性;
转JSON什么都没有,因为 arr 是空数组呀,所以取到的值肯定是 [];


引申,其实数组作为特殊的对象,他的 index,本身也是他的属性,计算在length里面,你设置的 school,team 也是属性,不算在length里,通常遍历的时候,都是按照 index 遍历的,属性不遍历,如果你设置 index 的属性,默认就是设置了数组中的项了,比如你上面的代码改下,就是不同的结果:

clipboard.png

因为JSON.stringify处理数组对象的时候不是枚举而是遍历,就是按照 0length - 1 的顺序处理,而处理{}对象的时候,是用枚举把对象的可枚举属性都处理一次。

就是

for(var i = 0; i < arr.length; i++) {}

for(var i in obj) {}

的区别


详细可以看看MDN上关于JSON 的 Polyfill
序列化数组的时候是这样操作的

// ...
else if (isArray(value)) {
    var res = '[';
    for (var i = 0; i < value.length; i++)
        res += (i ? ', ' : '') + stringify(value[i]);
// ...

其实这个我感觉不算错只能说不符合规范
Array继承自Object所以可以以对象的形式操作 以对象形式设置的值也可以通过for...in遍历出
只不过是JSON.stringify遍历数组的时候应该做了判断用for循环遍历下标的方式
关于可枚举和可迭代在MDN,for...of中有下面代码

Object.prototype.objCustom = function() {}; 
Array.prototype.arrCustom = function() {};

let iterable = [3, 5, 7];
iterable.foo = 'hello';

for (let i in iterable) {
  console.log(i); // logs 0, 1, 2, "foo", "arrCustom", "objCustom"
}

for (let i in iterable) {
  if (iterable.hasOwnProperty(i)) {
    console.log(i); // logs 0, 1, 2, "foo"
  }
}

for (let i of iterable) {
  console.log(i); // logs 3, 5, 7
}

数组对象的迭代器以数字型下标为key来遍历对象

新手上路,请多包涵
const transFormLajiArr = (arr) => {
    let arrStr = ""
    Object.keys(arr).forEach((k, index) => {
        arrStr += `"${k}":"${arr[k]}",`
    })
    arrStr = '[' + arrStr.substr(0, arrStr.length - 1) + ']';
    return arrStr
}

const arr = [];
arr['uname'] = '小明';
arr['age'] = 20;
// 给关联数组序列化
console.log(arr);
console.log(transFormLajiArr(arr));

image

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
宣传栏