ES6-10笔记(object新特性)
Object新特性
Enhanced Object Properties
Property Shorthand
ES5中Object的属性必须是key-value形式
var x = 0, y = 0;
obj = { x: x, y: y };
ES6中当key与value相同时可以简写这种形式
var x = 0, y = 0
obj = { x, y }
Computed Property Names
在 ES6 之前 Object 的 key 在定义时必须是字符串,如果想增加“动态”的 key,必须是先计算出 key,利用 object[key] = value 的方式来修改;
在 ES6 之后可以直接用变量或者表达式来定义 key
let obj = {
foo: 'bar',
['baz'+ quux()]: 42
}
Method Properties
ES5中Object的属性只支持常规函数,对异步函数式不支持的
var obj = {
foo: function (a, b) {
},
bar: function (x, y) {
}
// quux: no equivalent in ES5
}
ES6中对象内的方法可以简写,包括常规函数和异步函数
let obj = {
foo (a, b) {
},
bar (x, y) {
},
* quux (x, y) {
}
}
Set
生成Set实例
let s = new Set()
let s = new Set([1, 2, 3, 4])
//初始化的参数必须是可遍历的,可以是数组或者自定义遍历的数据结构
添加数据
s.add('hello')
s.add('goodbye')
s.add('hello').add('goodbye')
//Set 数据结构不允许数据重复,所以添加重复的数据是无效的
删除数据
删除数据分两种,一种是删除指定的数据,一种是删除全部数据
// 删除指定数据
s.delete('hello') // true
// 删除全部数据
s.clear()
统计数据
Set 可以快速进行统计数据,如数据是否存在、数据的总数
// 判断是否包含数据项,返回 true 或 false
s.has('hello') // true
// 计算数据项总数
s.size // 2
查询数据
- keys():返回键名的遍历器
- values():返回键值的遍历器
- entries():返回键值对的遍历器
- forEach():使用回调函数遍历每个成员
- for…of:可以直接遍历每个成员
console.log(s.keys()); // SetIterator {"hello", "goodbye"}
console.log(s.values()); // SetIterator {"hello", "goodbye"}
console.log(s.entries()); // SetIterator {"hello" => "hello", "goodbye" => "goodbye"}
s.forEach(item => {
console.log(item) // hello // goodbye
})
for (let item of s) {
console.log(item)
}
// hello// goodbye
Map
生成实例
let map = new Map([iterable])
//Iterable 可以是一个数组或者其他 iterable 对象,其元素为键值对(两个元素的数组,例如: [[ 1, ‘one’ ],[ 2, ‘two’ ]])。 每个键值对都会添加到新的 Map。null 会被当做 undefined
添加数据
let keyObj = {}
let keyFunc = function () {}
let keyString = 'a string'
// 添加键
map.set(keyString, "和键'a string'关联的值")
map.set(keyObj, '和键keyObj关联的值')
map.set(keyFunc, '和键keyFunc关联的值')
删除数据
// 删除指定的数据
map.delete(keyObj)
// 删除所有数据
map.clear()
统计数据
// 统计所有 key-value 的总数
console.log(map.size) //2
// 判断是否有 key-value
console.log(map.has(keyObj)) // true
查询数据
- get() 方法返回某个 Map 对象中的一个指定元素
- keys() 返回一个新的 Iterator 对象。它包含按照顺序插入 Map 对象中每个元素的 key 值
- values() 方法返回一个新的 Iterator 对象。它包含按顺序插入Map对象中每个元素的 value 值
- entries() 方法返回一个新的包含 [key, value] 对的 Iterator ?对象,返回的迭代器的迭代顺序与 Map 对象的插入顺序相同
- forEach() 方法将会以插入顺序对 Map 对象中的每一个键值对执行一次参数中提供的回调函数
- for…of 可以直接遍历每个成员
console.log(map.get(keyObj)) // 和键keyObj关联的值
console.log(map.keys()) // Iterator
console.log(map.values()) // Iterator
console.log(map.entries()) // Iterator
map.forEach((value, key, map) => {
console.log(value, key, map)
}, thisArg)
for ([key, value] of map) {
console.log(key, value)
}
Object和Map的区别
-
键的类型
一个Object的键只能是字符串或者 Symbols,但一个 Map 的键可以是任意值,包括函数、对象、基本类型。
-
键的顺序
Map 中的键值是有序的,而添加到对象中的键则不是。因此,当对它进行遍历时,Map 对象是按插入的顺序返回键值。
-
键值对的统计
你可以通过 size 属性直接获取一个 Map 的键值对个数,而 Object 的键值对个数只能手动计算。
-
键值对的遍历
Map 可直接进行迭代,而 Object 的迭代需要先获取它的键数组,然后再进行迭代。
-
性能
Map 在涉及频繁增删键值对的场景下会有些性能优势
Set和Map的区别
Set 是无重复值的有序列表。根据 Object.is()
方法来判断其中的值不相等,以保证无重复。 Set 会自动移除重复的值,因此你可以使用它来过滤数组中的重复值并返回结果。 Set并不是数组的子类型,所以你无法随机访问其中的值。但你可以使用has()
方法来判断某个值是否存在于 Set 中,或通过 size
属性来查看其中有多少个值。 Set 类型还拥有forEach()
方法,用于处理每个值。
Map 是有序的键值对,其中的键允许是任何类型。与 Set 相似,通过调用 Object.is()
方法来判断重复的键,这意味着能将数值 5 与字符串 "5" 作为两个相对独立的键。使用set()
方法能将任何类型的值关联到某个键上,并且该值此后能用 get()
方法提取出来。Map 也拥有一个 size
属性与一个 forEach()
方法,让项目访问更容易。
Object.assign
object.assign方法实行的是浅拷贝,而不是深拷贝
Object.assign() 方法用于将所有可枚举属性的值从一个或多个源对象复制到目标对象。它将返回目标对象。
如果目标对象中的属性具有相同的键,则属性将被源对象中的属性覆盖。后面的源对象的属性将类似地覆盖前面的源对象的属性
如果源对象的属性值是一个对象的引用,会直接指向该引用。如下例子中,因为source的一个键a指向的是一个对象。所以在拷贝过程中只是将target的键a也指向该对象。所以每次更改a键下的内容,都会导致全局所有的相关输出随之改变,因为他们都指向同一个对象
const target = {a:{b:1,c:2},e:2}
const source = {a:{b:3},e:2,f:2}
Object.assign(target,source)
console.log(target)
console.log(source)
//截至此时控制面板输出为
//{a: {b:3}, e: 2, f: 2}
//{a: {b:3}, e: 2, f: 2}
target.e = 10
source.e = 20
console.log(target)
console.log(source)
//截至此时控制面板输出为
//{a: {b:3}, e: 2, f: 2}
//{a: {b:3}, e: 2, f: 2}
//{a: {b:3}, e: 10, f: 2}
//{a: {b:3}, e: 20, f: 2}
target.a.b = 100
console.log(target)
console.log(source)
//截至此时控制面板输出为
//{a: {b:100}, e: 2, f: 2}
//{a: {b:100}, e: 2, f: 2}
//{a: {b:100}, e: 10, f: 2}
//{a: {b:100}, e: 20, f: 2}
//{a: {b:100}, e: 20, f: 2}
//{a: {b:100}, e: 20, f: 2}
source.a.b = 1000
console.log(target)//{a: {b:1000}, e: 10, f: 2}
console.log(source)//{a: {b:1000}, e: 20, f: 2}
//截至此时控制面板输出为
//{a: {b:1000}, e: 2, f: 2}
//{a: {b:1000}, e: 2, f: 2}
//{a: {b:1000}, e: 10, f: 2}
//{a: {b:1000}, e: 20, f: 2}
//{a: {b:1000}, e: 10, f: 2}
//{a: {b:1000}, e: 20, f: 2}
target.a.h = 200
console.log(target)//{a: {b:1000,h:200}, e: 20, f: 2}
console.log(source)//{a: {b:1000}, e: 20, f: 2}
//截至此时控制面板输出为
//{a: {b: 1000, h: 200}, e: 2, f: 2}
//{a: {b: 1000, h: 200}, e: 2, f: 2}
//{a: {b: 1000, h: 200}, e: 10, f: 2}
//{a: {b: 1000, h: 200}, e: 20, f: 2}
//{a: {b: 1000, h: 200}, e: 10, f: 2}
//{a: {b: 1000, h: 200}, e: 20, f: 2}
//{a: {b: 1000, h: 200}, e: 20, f: 2}
//{a: {b: 1000, h: 200}, e: 20, f: 2}
Object.assign的一些常用应用
- 为对象添加属性,方法
class Point {
constructor(x, y) {
Object.assign(this, {x, y});
}
}
Object.assign(SomeClass.prototype, {
someMethod(arg1, arg2) {
···
},
anotherMethod() {
···
}
});
// 等同于下面的写法
SomeClass.prototype.someMethod = function (arg1, arg2) {
···
};
SomeClass.prototype.anotherMethod = function () {
···
};
- 复制一个对象
const obj = { a: 1 };
const copy = Object.assign({}, obj);
console.log(copy); // { a: 1 }
- 合并多个对象
const o1 = { a: 1 };
const o2 = { b: 2 };
const o3 = { c: 3 };
const obj = Object.assign(o1, o2, o3);
console.log(obj); // { a: 1, b: 2, c: 3 }
console.log(o1); // { a: 1, b: 2, c: 3 }, 注意目标对象自身也会改变。
console.log(o2); // {b: 2}
console.log(o3); // {c: 3}
const merge = (target, ...sources) => Object.assign(target, ...sources);
const merge = (...sources) => Object.assign({}, ...sources);
//和空对象合并后返回一个全新对象
- 合并具有相同属性的对象
const o1 = { a: 1, b: 1, c: 1 };
const o2 = { b: 2, c: 2 };
const o3 = { c: 3 };
const obj = Object.assign({}, o1, o2, o3);
console.log(obj); // { a: 1, b: 2, c: 3 }