数组与对象相互转换

106 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第1天,点击查看活动详情

数组与对象转换有哪些方式?

对象转换成数组有四种方式:

  • Object.keys
  • Object.values
  • Object.entries
  • for in

数组转换成对象则通过 Object.fromEntries 实现。

const zoo = {
  lion: '🦁',
  panda: '🐼',
};

Object.keys(zoo);
// ['lion', 'panda']

Object.values(zoo);
// ['🦁', '🐼']

const arr = Object.entries(zoo);
// [ ['lion', '🦁'], ['panda', '🐼'] ]

// 数组转换成对象
Object.fromEntries(array);
// {
//   lion: '🦁',
//   panda: '🐼',
// }


const numbers = {
  one: 1,
  two: 2,
};

const keys = [];

// 通过 for in 遍历对象
for (const number in numbers) {
  if (numbers.hasOwnProperty(number)) {
    keys.push(number);
  }
}

keys; // [ 'one', 'two' ]

Object.keys 存在哪些问题?

MDN Object.keys

不能保证 Object.keys 返回的字段顺序。

JS 中对象的属性是无序的,所以 Object.keys 迭代的顺序依赖于浏览器实现。不同的浏览器实现的方式也不一样。

keys 数组分为三个规则进行排序:

  1. 可以作为数组索引的 key 按照升序。
  2. 字符串按照创建顺序排列。
  3. symbol 类的 key 按照创建顺序排列。

如何保证对象属性的顺序?

通过 ownPropertyKeys 对象属性遍历的顺序。

基于内部 ownPropertyKeys 方法实现的方法有 Object.getOwnPropertyNamesReflect.ownKeys,这两种方法保证对象属性的顺序。

Reflect.ownKeys 有兼容性问题,但是可以打印出 Symbol 的属性。

const key = Symbol('text');
const obj = {
    name: 'kane',
    1: 988,
    age: '18',
    [key]: 'hi',
  [Symbol('test')]: 'Symbol test',
  [Symbol.for('fn')]: () => 'symbol fn'
}

Object.keys(obj)
Object.getOwnPropertyNames(obj) 

// 查看属性
Reflect.ownKeys(obj)

// 获取对象的 symbol 属性
obj[Object.getOwnPropertySymbols(obj)[0]]

// 调用对象的 symbol 方法
console.log(obj[Symbol.for('fn')]())

如何判断空对象?

const empty = {};

Object.keys(empty).length === 0 && empty.constructor === Object
// true

为什么还需要 constructor 进行判断? 众所周知在JS中一切皆对象 增加 constructor 进行判断是为了覆盖包装器实例。

// bad case
function emptyCheck(value) {
  return Object.keys(value).length === 0;
}

emptyCheck(new String());    // true
emptyCheck(new Number());    // true
emptyCheck(new Boolean());   // true
emptyCheck(new Array());     // true
emptyCheck(new RegExp());    // true
emptyCheck(new Function());  // true
emptyCheck(new Date());      // true

如果将函数拓展成公共方法 isEmpty,还需要增加对 null undefined 的判断。

function emptyCheck(value) {
  return value && Object.kObject.keys(empty).length === 0 && empty.constructor === Object
}

// Empty Object Check in Older Browsers
function isObjectEmpty(value) {
  return (
    Object.prototype.toString.call(value) === '[object Object]' &&
    JSON.stringify(value) === '{}'
  );
}