JavaScript将具有数字字符串的键强制转换为Numbers ...,但是Object.keys()不会

时间:2019-03-17 12:26:18

标签: javascript ecmascript-6

外部API返回以下形式的JSON结果:

{
    "data": {
        "1.0": 'foo',
        "2.3": 'bar',
        "3.6": 'baz'
    }
}

在这里,键"1.0", "2.3", "3.6"实际上应该被视为表示离散分类的字符串,而不是是沿连续轴的值。因此,此API将这些键作为字符串返回是完全有效的。

但是...(你能感觉到它对不对?)

在JS客户端中,我需要遍历这些键,这会带来麻烦:

  • 浏览器的JS引擎自动将所有这些键强制转换为Number
  • 使用Object.keys(myObject.data)返回...字符串!
  • 因此,您无法看到以下所有内容

let myObject = {
  "data": {
    "1.0": 'foo',
    "2.3": 'bar',
    "3.6": 'baz'
  }
}

console.log(myObject.data)
for (let k in Object.keys(myObject.data)) {
  console.log(k, myObject.data[k])
}

// {
//     1.0: 'foo',
//     2.3: 'bar',
//     3.6: 'baz
// }
// "1.0" undefined
// "2.3" undefined
// "3.6" undefined

这里似乎有两个矛盾的地方:首先,对象键被转换为数字,但是同时,Object.keys()返回的是字符串而不是数字。

是否有解决此问题的适当方法?

理想情况下,我希望对象的实际键保持字符串不变。将值从Object.keys()转换为Numbers将导致相当麻烦的解决方法,因为API有时可以(并且确实)返回“真实的”字符串作为键(例如{ "red": 'foo', "blue": 'bar' }

3 个答案:

答案 0 :(得分:8)

您的问题是for in

for in尝试访问由Object.keys(obj.data)创建的数组中的键,该键实际上是索引

let obj = {"data": {"1.0": 'foo',"2.3": 'bar',"3.6": 'baz'}}

Object.keys(obj.data).forEach(e=>{
  console.log(typeof e)
})

//You can simply drop of Object.keys 

for (let k in obj.data) {
  console.log(k, obj.data[k])
}

答案 1 :(得分:6)

根本不使用Object.keys

let myObject = {
  "data": {
    "1.0": 'foo',
    "2.3": 'bar',
    "3.6": 'baz'
  }
}

console.log(myObject.data)
for (let k in myObject.data) {
  console.log(k, myObject.data[k])
}

一些解释:

Object.keys会执行所说的操作-从传入的对象中提取密钥,并将其作为数组返回(在您的情况下为<{1>} )。因此,当您尝试使用[ "1.0", "2.3", "3.6"]进行遍历时,实际上是遍历该结果数组,而不是实际对象,并且for..in变量将收到一个 index 数组中的相应项(对于key 0,对于"1.0"1,等等)。 "2.3" works就是这样。如果您想遍历数组的值,则可以使用for..in as another option。或者,就您的情况而言,就像我上面提到的那样,请不要使用for..of

答案 2 :(得分:3)

问题出在for..in循环上,请尝试for..of解决此问题。 for..in循环将迭代对象本身的所有可枚举属性以及对象从其构造函数的原型继承的那些属性。

另一方面,for..of主要关注可迭代对象的值,在这种情况下,它是Object.keys()调用返回的数组。

var myObject = {
    "data": {
        "1.0": 'foo',
        "2.3": 'bar',
        "3.6": 'baz'
    }
}
console.log(myObject.data)
for (let k of Object.keys(myObject.data)) {
    console.log(k, myObject.data[k])
}

在这里,当您遍历Object.keys(myObject.data)时,它将考虑返回数组的索引(数组对象的键),而不是myObject.data数组的实际值。

这里是一个区别,上面有一个小例子:

var arr = [10, 20, 30];
console.log("**for - in loop**")
//logs indices 0, 1, 2
for (i in arr){
  console.log(i);
}
console.log("**for - of loop**")
//logs values in the array 10, 20, 30
for (i of arr){
  console.log(i);
}