最近在做一个项目时,遇到一个遍历对象属性的需求(后来我才知道专业的叫法应该是遍历对象的键值),我使用了熟悉的 Object.kes() 方法去将对象的属性生成一个数组,然后接着对每个属性进行一些操作。

代码如下:

{
    "cat": {
        "name": "猫",
        "url": "./assets/images/cat.jpg",
        "title": "一只正在看着电脑屏幕的夜猫子"
    },
    "dog": {
        "name": "小狗",
        "url": "./assets/images/dog.jpg",
        "title": "一只可爱的小狗"
    },
    "planet": {
        "name": "星球",
        "url": "./assets/images/planet.jpg",
        "title": "令人震撼的星球"
    },
    "grass": {
        "name": "草丛",
        "url": "./assets/images/grass.jpg",
        "title": "一片生意盎然的草地"
    },
    "magic": {
        "name": "魔幻",
        "url": "./assets/images/magic.jpg",
        "title": "具有魔幻色彩的世界"
    }
}
import images from './data.json'

Object.keys(images).forEach((item) => {
    console.log(item.name)
})

结果

为什么会出现这种情况呢?因为 Object.keys() 方法返回的是参数对象自身的(不含继承的)所有可遍历属性的键名组成的数组。

对象的键名和键值

这里出现了一个很重要的概念——键名。我们知道一个对象是有一个或多个键值对组成,每个键值对都包含一个键名和一个键值。

cat: {
    name: '猫',
    url: './assets/images/cat.jpg',
    title: '一只正在看着电脑屏幕的夜猫'
},

如,上面这个对象就包含了3个键值对,第一个键值对是 name: '猫',键名是 'name' ,键值是 '猫'。键名一定是字符串类型,而键值则不一定是字符串类型。因为键值也可能是一个对象,比如这个

const images = {
    cat: {
        name: '猫',
        url: './assets/images/cat.jpg',
        title: '一只正在看着电脑屏幕的夜猫子'
    }
}

images 对象包含了1个键值对,键值对的键名是 'cat',键值是下面这个对象

{
    name: '猫',
    url: './assets/images/cat.jpg',
    title: '一只正在看着电脑屏幕的夜猫子'
}

一句话总结,对象由一个或多个键值对组成,键名一定是字符串类型,而键值则不一定。

Object.keys() 方法

我们回到上面那个问题,再看一眼 index.js 的代码,结合上面说的 Object.keys() 返回的是一个由对象自身所有可遍历(不含继承的)的键名数组,我们又知道键名仅仅只是一个字符串,每次迭代中的 item 都仅仅是一个字符串,那item.name 自然也就是 undefined 的了。

所以,我们可以将代码改成这样

import images from './data.json'

Object.keys(images).forEach((item) => {
    console.log(images[item].name)
})

结果

拿到键名后,我们可以借助于原对象取得每个 item 的 name 值。

Object.values() 方法

可能是和我有着相同需求的程序员越来越多吧,ES7 引入了 Object.values() 方法,它返回一个由对象自身的(不含继承的)所有可遍历属性的键值。这个方法就能完美地完成我们的需求啦!修改后的代码如下:

import images from './data.json'

Object.values(images).forEach((item) => {
    console.log(item.name)
})

结果

总结

  1. Object.keys() 返回一个由对象自身的(不含继承的)所有可遍历属性的键名组成的数组
  2. Object.values() 返回一个由对象自身的(不含继承的)所有可遍历属性的键值组成的数组

此外,遍历对象的方法还有 for...in 以及 Object.entries() (返回一个由对象自身的(不含继承的)所有可遍历属性的键值对组成的数组),这里不再赘述。

最后,还有一点需要注意的是,如果我们的关注点仅仅是键值的话,而完全不需要使用键名的话,我们大可不必使用这个结构,将其改成数组形式更好,如

const images = [
    {
        name: '猫',
        url: './assets/images/cat.jpg',
        title: '一只正在看着电脑屏幕的夜猫子'
    },
    ...
]