属性简写表示法

如果对象的 key 和 value 一样,可以省略其中一个

  1. let name = '潜龙'
  2. let age = 24
  3. let obj = {
  4. name,
  5. age
  6. }
  7. console.log(obj)

image.png

对象的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)

image.png

Object.assign() 合并对象或复制

默认是对对象进行深拷贝的,但是我们需要注意的是,它只对最外层的进行深拷贝,也就是当对象内嵌套有对象的时候,被嵌套的对象进行的还是浅拷贝

使用…、slice、concat等进行拷贝也是一样的效果,只深拷贝最外层

当我们对于一个层次单一对象的时候,可以考虑这种方法,简单快捷。(也不支持undefined)

assign() 方法中需要传入两个对象, 将第二个对象数据,填充到第一个对象中
当第一个 对象为空时,相当于将第二个对象的属性,复制到第一个对象中

let x = {
  a: 3,
  b: 4
}

let y = {};
Object.assign(y, x);
console.log(y)

image.png

注意事项
如果 合并到的对象 和 被合并的对象中 有属性相同,则会被覆盖掉,如果有属性不存在,则会保存

let x = {
  a: 3,
  b: 4
}

let y = {
  c: 12,
  a: 666
};
Object.assign(y, x);
console.log(y)

image.png

这里可以看出, 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])
}

image.png

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)

image.png

Object.entries()

const obj = {
  name: 'imooc',
  web: 'www.imooc.com',
  course: 'es'
}
console.log(Object.entries(obj))

会返回一个二维数组, 数组的第一项表示 key, 第二项表示 value
image.png
与 for … of 结合使用

const obj = {
  name: 'imooc',
  web: 'www.imooc.com',
  course: 'es'
}
for (const [key, val] of Object.entries(obj)) {
  console.log(`${key}: ${val}`)
}

image.png

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)

image.png

将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)

image.png

应用场景

筛选出分数大于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)

image.png

其他两种和 Object.keys()类似的方式

Object.getOwnPropertyNames(obj)

Object.getOwnPropertyNames(obj).forEach(key => {
  console.log('getOwnPropertyNames: ',key, obj[key])
});

image.png

Reflect.ownKeys(obj)

Reflect.ownKeys(obj).forEach(key => {
  console.log('Reflect.ownKeys' ,key, obj[key])
});

image.png

对象属性描述 getOwnPropertyDescriptors

const obj = {
  name: 'imooc',
  course: 'es'
}

const desc = Object.getOwnPropertyDescriptors(obj)
console.log(desc)

image.png
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)
}

image.png
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'))

image.png

Rest & Spread

扩展运算符

扩展运算符可以用来进行对象的合并以及拷贝

对象的合并, 合并的时候,如果出现同名的属性,会进行属性值的覆盖, age 属性值被覆盖了

// 对象扩展
const obj1 = {
  name: '潜龙',
  age: 18
}
const obj2 = {
  school: 'imooc',
  age: 24
}

const obj3 = {...obj1, ...obj2}
console.log('obj3', obj3)

image.png
通过扩展运算符,重新赋值的对象, 属于深拷贝,原先对象属性值的改变,不会影响赋值对象的属性值

剩余运算符

const obj = {
  name: '潜龙',
  age: 18,
  school: 'imooc',
  work: '前端',
  course: 'es'
}

const {name, age, ...rest} = obj
console.log('rest', rest)

image.png
剩余运算符只能放在最后,即所有参数的后面,否则会报错