> 文章列表 > ES6(函数扩展、数组扩展)

ES6(函数扩展、数组扩展)

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

参数变量是默认声明的,所以不能用letconst再次声明

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]