一、数组新增的扩展
1-1 扩展运算符
// ES6通过扩展元素符 ... 将一个数组转为用逗号分隔的参数序列
console.log(...[1, 2, 3]) // 1 2 3
console.log([...document.querySelectorAll('div')]) // [<div>, <div>, <div>]
// 能够实现数组的浅拷贝
const a1 = [1, 2];
const a2 = [...a1];
console.log(a2) // [1, 2]
// 合并数组
const a1 = [1, 2];
const a2 = [3, 4];
const a3 = [...a1, ...a2];
console.log(a3) // [1, 2, 3, 4]
// 扩展运算符可以与解构赋值结合起来,用于生成数组
const [first, ...rest] = [1, 2, 3, 4, 5];
console.log(first) // 1
console.log(rest) // [2, 3, 4, 5]
// 将字符串转为真正的数组
console.log([...'hello']) // ['h', 'e', 'l', 'l', 'o']
// 可以将定义了遍历器(Iterator)接口的对象转为数组
let set = new Set(['a','b','c'])
console.log(set) // Set(3) {'a', 'b', 'c'}
console.log([...set]) // ['a', 'b', 'c']
1-2 构造函数 Array 新增的方法
Array.from() :可以将类似数组的对象和可遍历(iterable)的对象(包括 ES6 新增的数据结构 Set 和 Map)
// 基本用法
let obj = {
0: 'a',
1: 'b',
2: 'c',
length: 3
}
console.log(Array.from(obj)) // ['a', 'b', 'c']
// Array.from()第二个参数是一个函数,用来对每个元素进行处理,将处理后的值放入返回的数组
console.log(Array.from(obj,(item) => item+item)) // ['aa', 'bb', 'cc']
Array.of():用于将一组值,转换为数组
// 基本用法
console.log(Array.of(1, 2, 3)) // [1, 2, 3]
// 没有参数的时候,返回一个空数组
console.log(Array.of()) // []
// 当参数只有一个的时候,实际上是指定数组的长度,所以说Array.of()参数值不能少于两个
console.log(Array.of(3)) // [ , , ]
1-3 Array 实例对象新增的方法
copyWithin():将指定位置的成员复制到其他位置(会覆盖原有成员),然后返回当前数组
// 参数如下
arget(必需):从该位置开始替换数据。如果为负值,表示倒数。
start(可选):从该位置开始读取数据,默认为 0。如果为负值,表示从末尾开始计算。
end(可选):到该位置前停止读取数据,默认等于数组长度。如果为负值,表示从末尾开始计算。
// 将从 3 号位直到数组结束的成员(4 和 5),复制到从 0 号位开始的位置,结果覆盖了原来的 1 和 2
let arr = [1, 2, 3, 4, 5].copyWithin(0, 3)
console.log(arr) // [4, 5, 3, 4, 5]
find():找出第一个符合条件的数组成员
// 参数是一个回调函数,接受三个参数依次为当前的值、当前的位置和原数组
let a = [1, 2, 3, 4, 5].find(function(value, index, arr) {
return value > 3;
})
console.log(a) // 4
findIndex():返回第一个符合条件的数组成员的位置,如果所有成员都不符合条件,则返回-1
// 第一个参数是一个回调函数,接受三个参数依次为当前的值、当前的位置和原数组
// 第二个参数是绑定回调函数的this对象
let a = [1, 2, 3, 4, 5].findIndex(function(value, index, arr) {
return value > 4;
})
console.log(a) // 4
---------------------------------------------------------------
function fn(value, index, arr){
return value > this.age;
}
let arr = { age: 2 }
let b = [1, 2, 3, 4, 5].findIndex(fn, arr)
console.log(b) // 2
fill():使用给定值,填充一个数组
// 第一个参数是填充值,第二个和第三个参数分别是填充的起始位置和结束位置
console.log(new Array(3).fill(0)) // [0, 0, 0]
console.log(new Array(3).fill(0).fill(7, 1, 2)) // [0, 7, 0]
keys(),values(),entries(),
keys()是对键名的遍历、values()是对键值的遍历,entries()是对键值对的遍历
for(let key of ['a', 'b'].keys()){
console.log(key)
}
// 0
// 1
for(let value of ['a', 'b'].values()){
console.log(value)
}
// 'a'
// 'b'
for(let [key, value] of ['a', 'b'].entries()){
console.log(key, value)
}
// 0 'a'
// 1 'b'
includes():用于判断数组是否包含给定的值,返回一个布尔值,第二个参数表示搜索的起始位置,默认为0,
负数则表示倒数的位置
[1, 2, 3].includes(2) // true
[1, 2, 3].includes(4) // false
[1, 2, 3].includes(3, 3); // false
[1, 2, 3].includes(3, -1); // true
flat():将数组扁平化处理,返回一个新数组,对原数据没有影响,默认只会“拉平”一层,如果想要“拉平”多层的嵌套数组,可以将flat()方法的参数写成一个整数,表示想要拉平的层数,默认为1
console.log([1, 2, [3, [4, 5]]].flat()) // [1, 2, 3, [4, 5]]
console.log([1, 2, [3, [4, 5]]].flat(2)) // [1, 2, 3, 4, 5]
flatMap():对原数组的每个成员执行一个函数相当于执行Array.prototype.map(),然后对返回值组成的数组执行flat()方法。该方法返回一个新数组,不改变原数组,第二个参数,用来绑定遍历函数里面的this
// 等价于 [[2, 4], [3, 6], [4, 8]].flat()
console.log([2, 3, 4].flatMap((x) => [x, x * 2])) // [2, 4, 3, 6, 4, 8]
1-4 数组的空位
数组的空位是指数组的某一个位置没有任何值,ES6 则是明确将空位转为 undefined ,包括Array.from、扩展运算符、copyWithin()、fill()、entries()、keys()、values()、find() 和 findIndex()
1-5 sort() 排序算法稳定性
const arr = [
'peach',
'straw',
'apple',
'spork'
];
const stableSorting = (s1, s2) => {
if (s1[0] < s2[0]) return -1;
return 1;
};
arr.sort(stableSorting) // ["apple", "peach", "straw", "spork"]
二、对象新增的扩展
2-1 属性的简写
当对象键名与对应值名相等的时候,可以进行简写
const a = { b: b }
// 等价于
const a = { b }
// 注意:简写的对象方法不能用作构造函数,否则会报错
const obj = {
f() {
this.foo = 'bar';
}
};
new obj.f() // 报错
2-2 属性名表达式
// ES6 允许字面量定义对象时,将表达式放在括号内
let a = 'aaa'
let b = {
[a]: 'hello'
}
console.log(b['aaa']) // 'hello'
// 表达式还可以用于定义方法名
let obj = {
['h' + 'ello']() {
console.log('hello')
}
}
obj.hello() // 'hello'
// 属性名表达式与属性简写,不能同时使用,会报错
const foo = 'bar';
const bar = 'abc';
const baz = { [foo] }; // 报错
// 注意,属性名表达式如果是一个对象,默认情况下会自动将对象转为字符串[object Object]
const keyA = {a: 1}
const objA = {
[keyA]: 'valueA'
};
console.log(objA) // {[object Object]: 'valueA'}
2-3 super关键字
https://www.yuque.com/xiaotuzidehzy/euhezi/edy5n1
2-4 扩展运算符
let { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 };
console.log(x) // 1
console.log(y) // 2
console.log(z) // {a: 3, b: 4}
// 扩展运算符配合解构赋值是浅拷贝
let obj = { a: 1, b: 2 }
let { ...x } = obj
console.log(x) // {a: 1, b: 2}
// 等价于使用Object.assign()方法
2-5 属性的遍历
ES6 一共有 5 种方法可以遍历对象的属性
- for…in:循环遍历对象自身的和继承的可枚举属性(不含 Symbol 属性)
- Object.keys(obj):返回一个数组,包括对象自身的(不含继承的)所有可枚举属性(不含 Symbol 属性)的键名
- Object.getOwnPropertyNames(obj):返回一个数组,包含对象自身的所有属性(不含 Symbol 属性,但是包括不可枚举属性)的键名
- Object.getOwnPropertySymbols(obj):返回一个数组,包含对象自身的所有 Symbol 属性的键名
- Reflect.ownKeys(obj):返回一个数组,包含对象自身的(不含继承的)所有键名,不管键名是 Symbol 或字符串,也不管是否可枚举
属性遍历的次序规则
- 首先遍历所有数值键,按照数值升序排列
- 其次遍历所有字符串键,按照加入时间升序排列
- 最后遍历所有 Symbol 键,按照加入时间升序排
Reflect.ownKeys({ [Symbol()]:0, b:0, 10:0, 2:0, a:0 })
// ['2', '10', 'b', 'a', Symbol()]
2-6 对象新增的方法
https://www.yuque.com/xiaotuzidehzy/euhezi/pv5rg9三、函数新增的扩展
3-1 参数
```javascript // ES6允许为函数的参数设置默认值
function log(x, y = ‘b’) { console.log(x, y) } log(‘a’) // ‘a’ ‘b’
// 函数的形参是默认声明的,不能使用let或const再次声明
function foo(x = 5) { let x = 1; // error const x = 2; // error }
// 参数默认值可以与解构赋值的默认值结合起来使用
function foo({x, y = 5}) { console.log(x, y) } foo({x: 1}) // 1 5 foo() // 报错,参数为对象的时候才能进行解构,否则变量x和y就不会生成
// 设置默认值避免报错
function foo({x, y = 5} = {}) { console.log(x, y) } foo() // undefined 5 foo(1) // undefined 5
// 参数默认值应该是函数的尾参数,如果不是非尾部的参数设置默认值,实际上这个参数是没发省略的 function f(x = 1, y) { console.log(x, y) } f(, 1) // 报错
<a name="x5V6P"></a>
## 3-2 属性
**函数的length属性将返回没有指定默认值的参数个数**
```javascript
(function (a) {}).length // 1
(function (a = 5) {}).length // 0
(function (a, b, c = 5) {}).length // 2
// rest 参数也不会计入length属性
(function(...args) {}).length // 0
// 如果设置了默认值的参数不是尾参数,那么length属性也不再计入后面的参数了
(function (a = 0, b, c) {}).length // 0
(function (a, b = 1, c) {}).length // 1
函数的name属性返回该函数的函数名
var f = function () {};
console.log(f.name)// "f"
// 如果将一个具名函数赋值给一个变量,则 name 属性都返回这个具名函数原本的名字
const bar = function baz() {};
console.log(bar.name) // "baz"
// Function构造函数返回的函数实例,name属性的值为anonymous
(new Function).name // "anonymous"
const f = new Function()
console.log(f.name) // "anonymous"
// bind返回的函数,name属性值会加上bound前缀
function foo() {};
foo.bind({}).name // "bound foo"
3-3 作用域
https://www.yuque.com/xiaotuzidehzy/euhezi/kb4iul
3-4 严格模式
只要函数参数使用了默认值、解构赋值、或者扩展运算符,那么函数内部就不能显式设定为严格模式,否则会报错
// 报错
function doSomething(a, b = a) {
'use strict';
// code
}
// 报错
const doSomething = function ({a, b}) {
'use strict';
// code
};
// 报错
const doSomething = (...a) => {
'use strict';
// code
};
const obj = {
// 报错
doSomething({a, b}) {
'use strict';
// code
}
};
3-5 箭头函数
let p = {
a: function () {
var obj = {
b: () => {console.log(this)},
}
obj.b()
}
}
p.a() // {a: ƒ} 函数执行上下文的this值
// 箭头函数不绑定this, 它会捕获其定义时的位置上下文的this值, 作为自己的this值