#javascript #ecmascript-6
#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' }
.
Комментарии:
1. используйте цикл for of
2.
console.log(k, myObject.data[k])
выводит// 0 undefined 1 undefined
и не"1.0" undefined
выводит. Проверьте ответ @ CodeManiac .Object.keys()
возвращает массив. Вы можете просто использоватьfor (let k in myObject.data){}
вместо3. » движок JS браузера автоматически преобразовал все эти ключи в Number » — эм, нет, что заставляет вас так думать? Ключи объекта всегда являются строками (или символами), никогда числами.
Ответ №1:
Ваша проблема в 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. Можете ли вы сослаться на авторитетный источник для этого?
2. @jayarjo итерация массива с использованием for в
3. Ваш краткий способ формулирования ответов смутил меня. Конечно, это индексы, но массива, а не объекта.
4. Будет полезно, если вы добавите
for (let k in myObject.data) { }
к ответу5. @jayarjo
for in tries to access keys in array created by Object.keys(obj.data) which is actually index
я указал здесь массив
Ответ №2:
Просто не используйте 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.0", "2.3", "3.6"]
). Поэтому, когда вы пытаетесь выполнить цикл по этому с помощью for..in
, вы фактически выполняете цикл по результирующему массиву, вместо фактического объекта и key
переменной будет получен индекс соответствующего элемента из массива ( 0
для "1.0"
, 1
для "2.3"
и т.д.). Именно так for..in
работает. Если вы хотите вместо этого перебирать значения массива, вы могли бы использовать for..of
как другой вариант. Или в вашем случае, как я упоминал выше, просто не используйте Object.keys
.
Ответ №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)
, рассматриваются индексы (ключи объекта array) возвращаемого массива вместо фактических значений 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);
}
Комментарии:
1. Это недопустимое различие между
for...in
иfor..of
.