hzzzzzzzq / Blog

这是我记录博客的地方,希望能多写一些技术博客,JS、ES、React、Vue等
14 stars 0 forks source link

ES 6 系列 - 7. 对象的扩展 #8

Open hzzzzzzzq opened 2 years ago

hzzzzzzzq commented 2 years ago

对象的扩展

属性的简单表示

ES 6 允许将属性写在 {} 中,直接写入变量和函数,作为对象的属性和方法。这样的书写方式更加简洁。

const foo = 'foo';
function getName() {
  console.log('name');
}
const obj = { foo, getName };

console.log(obj); // { foo: 'foo', getName: ƒunction }

// ES 6
const obj = {
  foo: 'foo',
  getName: function () {
    console.log('name');
  },
};
console.log(obj); // { foo: 'foo', getName: function }

属性的可枚举性和遍历

可枚举性

对象的每个属性都有一个描述对象,用来控制该属性的行为。 Object.getOwnPropertyDescriptor 方法来获取该属性的描述对象。

const obj = { x: 1 };
console.log(Object.getOwnPropertyDescriptor(obj));
// {
//   "value": 1,
//   "writable": true,
//   "enumerable": true,
//   "configurable": true
// }

描述对象的 enumerable 属性,称为可枚举性,如果该属性为 false,就会被某些操作忽略。

操作会忽略 enumerablefalse 的属性。

属性遍历

const obj = { x: 1, y: 2, z: 3 };
for (let o in obj) {
  console.log(o);
}
// x
// y
// z
const obj = { x: 1, y: 2, z: 3 };
for (let o of Object.keys(obj)) {
  console.log(o);
}
// x
// y
// z
const obj = { x: 1, y: 2, z: 3 };
for (let o of Object.getOwnPropertyNames(obj)) {
  console.log(o);
}
// x
// y
// z
const obj = { [Symbol('x')]: 1, y: 2, z: 3 };
console.log(Object.getOwnPropertySymbols(obj));
// [Symbol(x)]
const obj = { [Symbol('x')]: 1, y: 2, z: 3, 1: 10, 2: 11 };
console.log(Reflect.ownKeys(obj));
// ['1', '2', 'y', 'z', Symbol(x)]

一共五种遍历 key 的方式,但是遍历的次序是有规则的。

  • 首先遍历所有数值,并按照升序排列
  • 其次遍历字符串,按照加入时间升序
  • 最后才是 Symbol,按照加入时间升序

对象的扩展运算符

解构赋值数组的扩展 中,我们分别提到过对象的解构赋值以及扩展运算符。

我们来看看扩展运算符在对象中的使用。

解构赋值

我们来回顾一下 解构赋值

const { x, y } = { x: 1, y: 2 };
console.log(x); // 1
console.log(y); // 2
const { x, ...obj } = { x: 1, y: 2, z: 3 };
console.log(x); // 1
console.log(obj); // { y: 1, z: 2 }

const { ...obj, z } = { x: 1, y: 2, z: 3 };
console.log(obj); // 报错
const { ...obj } = null;
const { ...obj } = undefined;
// TypeError

扩展运算符

对象的扩展运算符用于取出参数对象的所有可便利属性,拷贝到当前对象之中。

const obj = { x: 1, y: 2 };
const obj2 = { ...obj };
console.log(obj); // { x: 1, y: 2 }
const obj = { ...['1', '2', '3'] };
console.log(obj);
// { 0: '1', 1: '2', 2: '3' }
const obj = { ...{}, x: 1 };
console.log(obj); // { x: 1 }
const obj = { ...1 }; // 等同于 { ...Object(1) }
const obj2 = { ...true }; // { ...Object(true) }
const obj3 = { ...undefined }; // { ...Object(undefined) }
const obj4 = { ...null }; // { ...Object(null) }
const obj = { ...'hzq' };
console.log(obj); // { 0: 'h', 1: 'z', 2: 'q' }

对象新增的常用实例方法

Object.is()

Object.is() 是用来判断两个是否严格相等,与严格比较运算符 === 行为基本一致。

console.log(Object.is('hello', 'world')); // false
console.log(Object.is('hello', 'hello')); // true
console.log(Object.is({}, {})); // false

=== 不同点

console.log(+0 === -0); // true
console.log(NaN === NaN); // false

console.log(Object.is(+0, -0)); // false
console.log(Object.is(NaN, NaN)); // true

Object.assign()

Object.assign() 放啊主要用于对象的合并,将对象的所有可枚举属性复制到目标对象

const obj = {};
const obj1 = { x: 1 };
const obj2 = { y: 2 };
Object.assign(obj, obj1, obj2);
console.log(obj);
// { x: 1, y: 2 }

从上面我们可以看出,第一个参数就是目标对象,将后面对象的所有可枚举属性复制到第一个参数。

const obj = { x: 1 };
const obj1 = { x: 3, y: 2 };
const obj2 = { y: 4 };
Object.assign(obj, obj1, obj2);
console.log(obj);
// { x: 3, y: 4 }

const obj3 = { x: 3 };
console.log(Object.assign(obj3) === obj3);
// true
console.log(Object.assign(1));
// Number {1}
console.log(typeof Object.assign(1));
// object
console.log(Object.assign(undefined)); // 报错
console.log(Object.assign(null)); // 报错

Object.keys(),Object.values(),Object.entries()

Object.keys()

Obejct.keys()ES 5 引入的,我们还是在这里稍微提一下。Object.keys()返回对象键值的数组,然后用来遍历对象的 key。

const obj = { x: 1, y: 2, z: 3 };
for (let key of Object.keys(obj)) {
  console.log(key);
}
// x
// y
// z

Object.values()

Object.values()ES 6 时引入的,返回一个数组,是每个键对应的值。返回值的顺序可以参照,对象的可枚举性中顺序。

当然许多特性是类似的。

const objVal = { 1: 'a', 2: 'b', 7: 'c' };
console.log(Object.values(objVal));
// ["b", "c", "a"]
const obj = { [Symbol()]: 1, x: 2, y: 3 };
console.log(Object.values(obj));
// [2, 3];
const str = 'hello';
console.log(Object.values(str));
// ['h', 'e', 'l', 'l', 'o'];
console.log(Object.values(true));
// []
console.log(Object.values(11));
// []

Object.entries()

Object.entries() 方法返回一个数组,成员是参数对象自身的所有可遍历属性的键值对数组。

const obj = { x: 1, y: 2, z: 3 };
console.log(Object.entries(obj));
// [["x", 1], ["y", 2], ["z", 3]]
const obj = { [Symbol()]: 1, x: 2 };
console.log(Object.entries(obj));
// [['x', 2]]

两个用途

const obj = { x: 1, y: 2 };
for (let [k, v] of Object.entries(obj)) {
  console.log(`key = ${k}, val = ${v}`);
}
// key = x, val = 1
// key = y, val = 2
const obj = { x: 1, y: 2 };
const map = new Map(Object.entries(obj));
console.log(map);
// Map { x: 1, y: 2 }

Object.fromEntries()

Object.fromEntries()Object.entries() 的逆向操作,用于将一个键值对数组转为对象

const arr = [
  ['x', 1],
  ['y', 2],
  ['z', 3],
];
console.log(Object.fromEntries(arr));
// { x: 1, y: 2, z: 3 }

用途

主要作用就是,是将键值对的数据结构还原为对象

let map = new Map();
map.set('x', 1);
map.set('y', 2);
map.set('z', 3);
console.log(Object.fromEntries(map));
// { x: 1, y: 2, z: 3 }

对象的扩展,我们就先介绍到这里,如果有问题,会对文章进行更新。

感谢各位的观看!