属性简写表示法
如果对象的 key 和 value 一样,可以省略其中一个
let name = '潜龙'
let age = 24
let obj = {
name,
age
}
console.log(obj)
对象的key值使用变量
正常情况
let name = '潜龙‘
let obj = {
name,
school: 'imooc'
}
key 值使用变量后
let name = '潜龙‘
let s = 'school'
let obj = {
name,
[s]: 'imooc'
}
对象内方法的简写
简写 对象内方法时,一定不能使用 箭头函数, this指向的是 对象声明的地方,是无法拿到对象内的属性的
正常写法
let obj1 = {
name: '潜龙',
study: function() {
console.log(this.name + '在学习 ES6')
}
}
obj1.study() // 潜龙在学习 ES6
简写
let obj = {
name: '潜龙',
study() {
console.log(this.name + '在学习 ES6')
}
}
obj.study() // 潜龙在学习 ES6
错误示范箭头函数
let obj2 = {
name: '潜龙',
study: () => {
console.log(this.name + '在学习 ES6')
}
}
obj2.study() // 在学习 ES6
从打印的数据可以看出,箭头函数内的 this.name 无法获取到对象中 声明的 name值
Object.is() 判断是否相等
这个方法与 === 的作用类似, 但是也存在不同的地方
偏向于比较 类型
比较值相同的 字符串与数字
console.log(2 == '2'); // true
console.log(2 === '2') // false
console.log(Object.is(2, '2')) // false
比较 NaN
console.log(NaN == NaN); // false
console.log(Object.is(NaN, NaN)); // true
比较 key 与value 完全相同的 两个对象
let obj1 = {
name: '潜龙',
age: 24
}
let obj2 = {
name: '潜龙',
age: 24
}
console.log(Object.is(obj1, obj2)) // false
因为 对象之间比较的 是 存储在 堆内存中 的 内存空间,所以会导致 false, 存储在栈内存中的也只是 object 的 内存引用地址
扩展运算符在 对象中的应用
let x = {
a: 3,
b: 4
}
let y = {...x};
console.log('y', y)
Object.assign() 合并对象或复制
默认是对对象进行深拷贝的,但是我们需要注意的是,它只对最外层的进行深拷贝,也就是当对象内嵌套有对象的时候,被嵌套的对象进行的还是浅拷贝
使用…、slice、concat等进行拷贝也是一样的效果,只深拷贝最外层
当我们对于一个层次单一对象的时候,可以考虑这种方法,简单快捷。(也不支持undefined)
assign() 方法中需要传入两个对象, 将第二个对象数据,填充到第一个对象中
当第一个 对象为空时,相当于将第二个对象的属性,复制到第一个对象中
let x = {
a: 3,
b: 4
}
let y = {};
Object.assign(y, x);
console.log(y)
注意事项
如果 合并到的对象 和 被合并的对象中 有属性相同,则会被覆盖掉,如果有属性不存在,则会保存
let x = {
a: 3,
b: 4
}
let y = {
c: 12,
a: 666
};
Object.assign(y, x);
console.log(y)
这里可以看出, y 对象 中的 属性 a 被覆盖了
in 判断 对象 有无该属性
let obj = {
a: 12
}
console.log('a' in obj) // true
console.log(12 in obj) // false
这里可以看出 in 只能用来判断 ,对象下是否有该属性
同样 in 在数组中也有应用,不过和 对象不同, 数组中 的 in 主要是用来判断 该 下标位置有无值
let arr = [1, 4, 3];
console.log(3 in arr); // false
console.log(2 in arr); // true
数组中下标 2的值 为 3 因此返回 true, 下标3 没有数值,所以为 false
遍历对象
使用 for in 遍历对象
let obj = {
name: '潜龙',
age: 34,
school: 'imooc'
}
for (let objKey in obj) {
console.log(objKey, obj[objKey])
}
Object.keys()
可以获取到 对象中的 key ,即属性名, 并且返回数组, 取到 Object的 属性名 后,就可以实现对象的遍历
let obj = {
name: '潜龙',
age: 34,
school: 'imooc'
}
let objKeyArr = Object.keys(obj)
console.log('objKeyArr' ,objKeyArr)
// objKeyArr (3) ["name", "age", "school"]
Object.keys(obj).forEach(key => {
console.log(key, obj[key])
})
// name 潜龙
// age 34
// school imooc
Object.values()
可以将 对象中的 所有属性返回一个数组,这样我们就可以直接遍历 对象的值
let obj = {
name: '潜龙',
age: 34,
school: 'imooc'
}
const valueArr = Object.values(obj)
console.log('valueArr', valueArr)
Object.entries()
const obj = {
name: 'imooc',
web: 'www.imooc.com',
course: 'es'
}
console.log(Object.entries(obj))
会返回一个二维数组, 数组的第一项表示 key
, 第二项表示 value
与 for … of 结合使用
const obj = {
name: 'imooc',
web: 'www.imooc.com',
course: 'es'
}
for (const [key, val] of Object.entries(obj)) {
console.log(`${key}: ${val}`)
}
Object.fromEntries()
与Object.entries()
方法互逆,Object.entries()
会将对象转化成类似map
结构的数组数据,而 Object.fromEntries()
则是将其转化成对象类型数据
const obj = {
name: 'imooc',
course: 'es'
}
const entries = Object.entries(obj)
console.log('entries', entries)
const fromEntries = Object.fromEntries(entries)
console.log('fromEntries', fromEntries)
将Map转化成Object
const map = new Map()
map.set('name', 'imooc')
map.set('course', 'es')
console.log('map', map)
const fromEntries = Object.fromEntries(map)
console.log('fromEntries', fromEntries)
应用场景
筛选出分数大于80分的科目, 并返回一个对象类型
const course = {
math: 80,
english: 85,
chinese: 90
}
const res = Object.entries(course).filter(([key, val]) => val>80)
console.log('res', res)
const obj = Object.fromEntries(res)
console.log('obj', obj)
其他两种和 Object.keys()类似的方式
Object.getOwnPropertyNames(obj)
Object.getOwnPropertyNames(obj).forEach(key => {
console.log('getOwnPropertyNames: ',key, obj[key])
});
Reflect.ownKeys(obj)
Reflect.ownKeys(obj).forEach(key => {
console.log('Reflect.ownKeys' ,key, obj[key])
});
对象属性描述 getOwnPropertyDescriptors
const obj = {
name: 'imooc',
course: 'es'
}
const desc = Object.getOwnPropertyDescriptors(obj)
console.log(desc)
value 表示当前对象属性的默认值
writable 表示当前对象属性值是否可以改
enumerable 表示当前属性值是否可以通过for in
的方式循环出来
configurable 表示当前属性值是否可以通过delete
进行删除
如何对这四个属性进行设置 Reflect.defineProperty()
Reflect.defineProperty(obj, 'name', {
value: '潜龙勿用',
writable: false,
configurable: false,
enumerable: false
})
Reflect.defineProperty(obj, 'age', {
value: 24,
writable: true,
configurable: true,
enumerable: true
})
console.log('obj', obj)
obj.name = '张三'
console.log('write obj', obj)
delete obj.name
console.log('delete obj', obj)
for (let key in obj) {
console.log('key', key)
}
name属性因为不可删除,所以delete没有生效,writable为false所以修改姓名也没有生效, 因为enumerable为false所以 for in 时,key值没有生效
Object.getOwnPropertyDescriptor()
只能用来查看对象中单个属性值的描述,加s就可以查看对象下所有属性值的描述
const obj = {}
Reflect.defineProperty(obj, 'name', {
value: '潜龙勿用',
writable: false,
configurable: false,
enumerable: false
})
console.log('单个属性描述', Object.getOwnPropertyDescriptor(obj, 'name'))
Rest & Spread
扩展运算符
扩展运算符可以用来进行对象的合并以及拷贝
对象的合并, 合并的时候,如果出现同名的属性,会进行属性值的覆盖, age 属性值被覆盖了
// 对象扩展
const obj1 = {
name: '潜龙',
age: 18
}
const obj2 = {
school: 'imooc',
age: 24
}
const obj3 = {...obj1, ...obj2}
console.log('obj3', obj3)
通过扩展运算符,重新赋值的对象, 属于深拷贝,原先对象属性值的改变,不会影响赋值对象的属性值
剩余运算符
const obj = {
name: '潜龙',
age: 18,
school: 'imooc',
work: '前端',
course: 'es'
}
const {name, age, ...rest} = obj
console.log('rest', rest)
剩余运算符只能放在最后,即所有参数的后面,否则会报错