尾调用实际用途——递归函数优化
在ES5时代,我们不推荐使用递归,因为递归会影响性能。
但是有了尾调用优化之后,递归函数的性能有了提升。
//新型尾优化写法 "use strict"; function a(n, p = 1) { if(n <= 1) { return 1 * p } let s = n * p return a(n - 1, s) } //求 1 x 2 x 3的阶乘 let sum = a(3) console.log(sum) // 6
五、ES6对象新增方法
Object.assign()
Object.assign()方法用于将所有可枚举属性的值从一个或多个源对象复制到目标对象。它将返回目标对象。
Object.assign 方法只会拷贝源对象自身的并且可枚举的属性到目标对象。该方法使用源对象的[[Get]]和目标对象的[[Set]],所以它会调用相关 getter 和 setter。因此,它分配属性,而不仅仅是复制或定义新的属性。如果合并源包含getter,这可能使其不适合将新属性合并到原型中。为了将属性定义(包括其可枚举性)复制到原型,应使用Object.getOwnPropertyDescriptor()和Object.defineProperty() 。
String类型和 Symbol 类型的属性都会被拷贝。
合并对象
var o1 = { a: 1 }; var o2 = { b: 2 }; var o3 = { c: 3 }; var obj = Object.assign(o1, o2, o3); console.log(obj); // { a: 1, b: 2, c: 3 } console.log(o1); // { a: 1, b: 2, c: 3 }, 注意目标对象自身也会改变。
合并具有相同属性的对象
var o1 = { a: 1, b: 1, c: 1 }; var o2 = { b: 2, c: 2 }; var o3 = { c: 3 }; var obj = Object.assign({}, o1, o2, o3); console.log(obj); // { a: 1, b: 2, c: 3 }
六、Map和Set
Map和Set都叫做集合,但是他们也有所不同。Set常被用来检查对象中是否存在某个键名,Map集合常被用来获取已存的信息。
Set是有序列表,含有相互独立的非重复值。
Array和Set对比
都是一个存储多值的容器,两者可以互相转换,但是在使用场景上有区别。如下:
Array的indexOf方法比Set的has方法效率低下
Set不含有重复值(可以利用这个特性实现对一个数组的去重)
Set通过delete方法删除某个值,而Array只能通过splice。两者的使用方便程度前者更优
Array的很多新方法map、filter、some、every等是Set没有的(但是通过两者可以互相转换来使用)
Object和Map对比
Object是字符串-值,Map是值-值
Object键为string类型,Map的键是任意类型
手动计算Object尺寸,Map.size可以获取尺寸
Map的排序是插入顺序
Object有原型,所以映射中有一些缺省的键。可以理解为Map=Object.create(null)
Set操作集合
let set = new Set() // Set转化为数组 let arr = Array.from(set) let arr = [...set] // 实例属性(继承自Set) set.constructor === Set set.size // 操作方法 set.add(1) // 添加一个值 set.delete(1) //删除一个值 set.has(1) //判断是否有这个值(Array中的indexOf) set.clear() //清除所有值 // 获取用于遍历的成员方法(Set的遍历顺序就是插入顺序) set.keys() // 返回键名的遍历器 set.values() // 返回键值得遍历器 set.entries() // 返回键值对的遍历器 set.forEach() // 循环遍历每个值(和Array的方法一致) for (let key of set.keys()){} for (let val of set.values()){} for (let entry of set.entries()){} // 使用数组方法来处理set值 set = new Set(arr) set = new Set([...set].map((x) => x = x * 2)) set = new Set([...set].filter((x) => x > 2))
Map的方法集合
let map = new Map() // 实例属性(继承自Map) map.constructor === Map map.size // 操作方法 map.set(1,2) map.get(1) map.delete(1) map.has(1) map.clear() // 遍历方法 map.keys() map.values() map.entries() map.forEach() // Map和数组的转换 map = new Map([['key','val'],[2,1]]) // 要求双成员数组 let arr = [...map] // 值得注意的是Map的键是跟内存绑定的 map.set([1], 's') map.get([1]) let arr = [1] let arr1 = [1] map.set(arr, 's') map.get(arr) map.set(arr1, 's') map.get(arr1)
七、迭代器(Iterator)
1、entries() 返回迭代器:返回键值对
//数组 const arr = ['a', 'b', 'c']; for(let v of arr.entries()) { console.log(v) } // [0, 'a'] [1, 'b'] [2, 'c'] //Set const arr = new Set(['a', 'b', 'c']); for(let v of arr.entries()) { console.log(v) } // ['a', 'a'] ['b', 'b'] ['c', 'c'] //Map const arr = new Map(); arr.set('a', 'a'); arr.set('b', 'b'); for(let v of arr.entries()) { console.log(v) } // ['a', 'a'] ['b', 'b']
2、values() 返回迭代器:返回键值对的value