走过路过不要错过,ES8/9中那些容易让你忽视的知识点,快来看一看呀!

220 阅读4分钟

「这是我参与2022首次更文挑战的第14天,活动详情查看:2022首次更文挑战」。

一、Object.values()

在之前我们要获取一个对象的每一个value值,需要进行如下处理:

let obj = {
    name: 'zhangsan',
    age: 18,
    sex: 'male'
}

let res = Object.keys(obj).map(key => obj[key])
console.log(res) //['zhangsan', 18, 'male']

Object.values()的出现可以让我们更直接的获取value。他返回一个包含对象自身的所有可枚举属性值得数组。

let obj = {
    name: 'zhangsan',
    age: 18,
    sex: 'male'
}

console.log(Object.values(obj)) //['zhangsan', 18, 'male']

我们肯定了解过for...in,我们是不是也可以用for...in处理上边的代码呢?不妨试一试,

let obj = {
    name: 'zhangsan',
    age: 18,
    sex: 'male'
}
for(let prop in obj) {
    console.log(obj[prop]); //'zhangsan', 18, 'male'
}

那么它与Object.values()有什么区别呢?

for...in以任意顺序遍历一个对象的除Symbol以外的可枚举属性,包括继承的可枚举属性 Object.values()只能遍历对象自身的可枚举属性值。

二、Object.entries()

Object.entries()返回给定对象自身的可枚举属性键值对数组,简单的说是一个二维数组。

let obj = {
    name: 'zhangsan',
    age: 18,
    sex: 'male'
}

console.log(Object.entries(obj));

image.png

当参数是一个数组时,他的第一个值是下标

let arr = ['a','b','c']

console.log(Object.entries(arr));

image.png

三、Object.getOwnPropertyDescriptors()

Object.getOwnPropertyDescriptors()用于获取对象自身属性描述符。

let obj = {name: '张三'}

console.log(Object.getOwnPropertyDescriptors(obj));

image.png 我们可以看到name属性下有四个值,这就是描述obj对象下name属性的描述符。

  • value的值就是name对应的值
  • configurable 描述的是该属性可不可以被delete删除 是个boolean类型
  • enumerable 描述的是该属性可不可以被for...in遍历 是个boolean类型
  • writable 描述的事该属性可不可以被修改 是个boolean类型

同样,我们也可以通过defineProperty来定义一个对象的属性的这些描述符

let obj = {name: '张三'}

Reflect.defineProperty(obj, 'name', {
    value: '李四',
    writable: false,
    enumerable: false,
    configurable: false
})

我们可以看到,Object.getOwnPropertyDescriptors()后面有一个s,我们也可以去掉这个s,当s去掉后,我们可以传第二个参数,第二个参数就是该对象下的某个属性。意思就是说,我们可以指定查看对象下某个属性的描述符

let obj = {name: '张三'}

console.log(Object.getOwnPropertyDescriptor(obj,'name'))
//{value: '张三', writable: true, enumerable: true, configurable: true}

四、ES9中的对象扩展

在ES9中,新增了对象的扩展运算,在之前,我们学过数组的扩展运算符,比如合并两个数组,我们就可以用数组的扩展运算符实现,代码如下:

let arr1 = [1,2,3]
let arr2 = [4,5,6]
let arr3 = [...arr1,...arr2]
console.log(arr3) //[1, 2, 3, 4, 5, 6]

其实对象也有扩展运算符,如下,我们可以克隆一个对象。

let obj1 = {
    name: {
        firstName: '三'
    }
}

let obj2 = {...obj1}

console.log(obj2)

image.png

可以看到这是完全可以的,但是上边的代码是个浅拷贝,这是一个要注意的问题。

let obj1 = {
    name: {
        firstName: '三'
    }
}

let obj2 = {...obj1}
obj1.name.firstName = '四'
console.log(obj2) 

image.png 可以看到,obj2的值也变了,所以是个浅拷贝

  • 同时,我们也可以合并两个对象,当对象中的属性重复时,后边的对象属性会覆盖前面对象的属性
let obj1 = {
    name: '张三',
    age: 18
}

let obj2 = {
    name: '李四',
    sex: 'male'
}

let obj3 = {...obj1, ...obj2}
console.log(obj3) //{name: '李四', age: 18, sex: 'male'}

同时,对象也可以用作剩余处理,例如下面的这段代码:

let obj = {
    name: 'zhangsan',
    age: 18,
    school: '家里蹲',
    sex: 'male'
}

let {name,age,...rest} = obj
console.log(name)   //zhangsan
console.log(age)   //18
console.log(rest) //{school: '家里蹲', sex: 'male'}

但是需要注意的是,...rest只能放在最后的位置,否则会报错

let obj = {
    name: 'zhangsan',
    age: 18,
    school: '家里蹲',
    sex: 'male'
}

let {name, ...rest, age} = obj

image.png

五、Promise.prototype.finally()

之前在学习Promise时,我们知道有then和catch方法,分别表示成功和失败的处理,而finally表示不管成功失败都要进行的回调函数。

new Promise((resolve,reject) => {
    setTimeout(() => {
        // resolve('success')
        reject('fail')
    },1000)
}).then(res => {
    console.log(res)
}).catch(err => {
    console.log(err)
}).finally(fin => {
    console.log('finally');
})

Promise.prototype.finally()的应用场景:

  • ajax发送请求时,在等待接口响应11前的loading动画,无论成功还是失败都要关闭loading,如果没有finally,我们需要在then和catch中都写一遍关闭代码。有了finally,我们只需要写在finally中就可以了。