ES6(函数扩展、数组扩展)
一、 函数扩展
1. 参数可以默认
ES5调用函数:如果给参数设置默认需要进行判断
ES6可以直接给参数设置默认
//ES5
function log(x, y) {//两种判断方法(传统分支判断、利用逻辑符)if (typeof y === 'undefined') {y = 'World';}//y = y || 'World';console.log(x, y);
}log('Hello') // Hello World
log('Hello', 'China') // Hello China
log('Hello', '') // Hello World
//ES6直接设置默认参数值
function log(x, y = 'World') {console.log(x, y);
}log('Hello') // Hello World
log('Hello', 'China') // Hello China
log('Hello', '') // Hello
参数变量是默认声明的,所以不能用
let
或const
再次声明
function foo(x = 5) {let x = 1; // errorconst x = 2; // error
}
2. 配合解构
参数默认值可以与解构赋值的默认值,结合起来使用
function foo({x, y = 5}) {console.log(x, y);
}foo({}) // undefined 5
foo({x: 1}) // 1 5
foo({x: 1, y: 2}) // 1 2
foo() // TypeError: Cannot read property 'x' of undefined
以下代码参数值先生效:然后对这个默认值进行解构
// 写法一
function m1({x = 0, y = 0} = {}) {return [x, y];
}// 写法二
function m2({x, y} = { x: 0, y: 0 }) {return [x, y];
}// 函数没有参数的情况
m1() // [0, 0]
m2() // [0, 0]// x 和 y 都有值的情况
m1({x: 3, y: 8}) // [3, 8]
m2({x: 3, y: 8}) // [3, 8]// x 有值,y 无值的情况
m1({x: 3}) // [3, 0]
m2({x: 3}) // [3, undefined]// x 和 y 都无值的情况
m1({}) // [0, 0];
m2({}) // [undefined, undefined]m1({z: 3}) // [0, 0]
m2({z: 3}) // [undefined, undefined]
3. 参数的位置
默认值的参数都不是尾参数。这时,无法只省略该参数,而不省略它后面的参数,除非显式输入
undefined
- 如果传入
undefined
,将触发该参数等于默认值,null
则没有这个效果
return [x, y, z];
}f() // [undefined, 5, undefined]
f(1) // [1, 5, undefined]
f(1, ,2) // 报错
f(1, undefined, 2) // [1, 5, 2]
function foo(x = 5, y = 6) {console.log(x, y);
}foo(undefined, null)
// 5 null
4.reset()剩余参数
...变量名:直接生成新数组
用于获取函数的多余参数,这样就不需要使用
arguments
对象了//对比一下argument和生产与参数的优势 // arguments变量的写法(先将伪数组变成真数组) function sortNumbers() {return Array.from(arguments).sort(); }// rest参数的写法(直接使用剩余参数然后变量排序) const sortNumbers = (...numbers) => numbers.sort();
function add(...values) {let sum = 0;for (var val of values) {sum += val;}return sum;
}add(2, 5, 3) // 10
5. 严格模式
只要函数参数使用了默认值、解构赋值、或者扩展运算符,那么函数内部就不能设定为严格模式
// 报错
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}
};
解决严格模式引起的麻烦
- 设定全局性的严格模式
- 函数包在一个无参数的立即执行函数里面
//设置全局严格
'use strict';function doSomething(a, b = a) {// code
}
//把函数抱在午餐的立即执行函数
const doSomething = (function () {'use strict';return function(value = 42) {return value;};
}());
6.箭头函数 (简化回调函数)
箭头函数不需要参数或需要多个参数,就使用一个圆括号代表参数部分
var f = () => 5;
// 等同于
var f = function () { return 5 };var sum = (num1, num2) => num1 + num2;
// 等同于
var sum = function(num1, num2) {return num1 + num2;
};
如果箭头函数的代码块部分多于一条语句,就要使用大括号将它们括起来,并且使用
return
语句返回
箭头函数直接返回一个对象,必须在对象外面加上括号,否则会报错
// 报错
let getTempItem = id => { id: id, name: "Temp" };// 不报错
let getTempItem = id => ({ id: id, name: "Temp" });
箭头函数注意点:
- 箭头函数没有自己的this
- 不可当作构造函数
- 不能使用伪数组,可以使用剩余参数
二、数组扩展
1. 扩展运算符
好比 rest 参数的逆运算,将一个数组转为用逗号分隔的参数序列
console.log(...[1, 2, 3])
// 1 2 3console.log(1, ...[2, 3, 4], 5)
// 1 2 3 4 5
function push(array, ...items) {array.push(...items);
}function add(x, y) {return x + y;
}const numbers = [4, 38];
add(...numbers) // 42
如果扩展运算符后面是一个空数组,则不产生任何效果。
[...[], 1] // [1]
函数调用时,扩展运算符才可以放在圆括号中,否则会报错。
(...[1, 2])
// Uncaught SyntaxError: Unexpected numberconsole.log((...[1, 2]))
// Uncaught SyntaxError: Unexpected numberconsole.log(...[1, 2])
// 1 2
2. 应用扩展运算符
复制数组
数组是复合的数据类型,直接复制的话,只是复制了指向底层数据结构的指针,而不是克隆一个全新的数组
const a1 = [1, 2];
const a2 = a1;a2[0] = 2;
a1 // [2, 2]
//a2并不是a1的克隆,而是指向同一份数据的另一个指针。修改a2,会直接导致a1的变化
解决
const a1 = [1, 2];
// 写法一
const a2 = [...a1];
// 写法二
const [...a2] = a1;
合并数组
const arr1 = ['a', 'b'];
const arr2 = ['c'];
const arr3 = ['d', 'e'];// ES5 的合并数组
arr1.concat(arr2, arr3);
// [ 'a', 'b', 'c', 'd', 'e' ]// ES6 的合并数组
[...arr1, ...arr2, ...arr3]
// [ 'a', 'b', 'c', 'd', 'e' ]
3.Array.from()
将类似数组的对象和可遍历对象转为数组
let arrayLike = {'0': 'a','1': 'b','2': 'c',length: 3
};// ES5 的写法
var arr1 = [].slice.call(arrayLike); // ['a', 'b', 'c']// ES6 的写法
let arr2 = Array.from(arrayLike); // ['a', 'b', 'c']
// arguments 对象
function foo() {var args = Array.from(arguments);// ...
}
4.Array.of()
Array.of()
方法用于将一组值,转换为数组
Array.of() // []
Array.of(undefined) // [undefined]
Array.of(1) // [1]
Array.of(1, 2) // [1, 2]
5. copyWithin()
Array.prototype.copyWithin(target, start = 0, end = this.length)
- target(必需):从该位置开始替换数据。如果为负值,表示倒数。
- start(可选):从该位置开始读取数据,默认为 0。如果为负值,表示从末尾开始计算。
- end(可选):到该位置前停止读取数据,默认等于数组长度。如果为负值,表示从末尾开始计算。
[1, 2, 3, 4, 5].copyWithin(0, 3)
// [4, 5, 3, 4, 5]// 将3号位复制到0号位
[1, 2, 3, 4, 5].copyWithin(0, 3, 4)
// [4, 2, 3, 4, 5]// -2相当于3号位,-1相当于4号位
[1, 2, 3, 4, 5].copyWithin(0, -2, -1)
// [4, 2, 3, 4, 5]
6. find(),findIndex(),findLast(),findLastIndex()
find()
方法找出数组中第一个小于 0 的成员:没有符合条件的成员,则返回undefined
[1, 4, -5, 10].find((n) => n < 0)
// -5
findIndex()
方法返回第一个符合条件的数组成员的位置:不符合条件,则返回-1
[1, 5, 10, 15].findIndex(function(value, index, arr) {return value > 9;
}) // 2
弥补indexOf查找不出 NaN
[NaN].indexOf(NaN)
// -1[NaN].findIndex(y => Object.is(NaN, y))
// 0
7. flat(参数)
拉平一个数组,参数(Infinity:全部)代表层数
[1, 2, [3, [4, 5]]].flat()
// [1, 2, 3, [4, 5]][1, 2, [3, [4, 5]]].flat(2)
// [1, 2, 3, 4, 5][1, [2, [3]]].flat(Infinity)
// [1, 2, 3]