导航
导航
文章目录
  1. 函数的扩展
    1. 一、函数参数的默认值
    2. 二、与解构赋值默认值结合使用
    3. 三、rest参数
    4. 四、扩展运算符(…)
    5. 五、箭头函数

读书笔记-es6函数的扩展

函数的扩展

一、函数参数的默认值

  • 参数变量是默认声明的,所以不能用let或const再次声明
  • 通常情况下,定义了默认值的参数,应该是函数的尾参数
1
2
3
4
5
6
function log(x, y = 'World') {
console.log(x, y);
}
log('Hello') // Hello World
log('Hello', 'China') // Hello China
log('Hello', '') // Hello

二、与解构赋值默认值结合使用

1
2
3
4
5
6
7
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

三、rest参数

ES6 引入 rest 参数(形式为“…变量名”),用于获取函数的多余参数,这样就不需要使用arguments对象了。rest 参数搭配的变量是一个数组,该变量将多余的参数放入数组中。

  • rest 参数之后不能再有其他参数(即只能是最后一个参数),否则会报错
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function add(...values) {
let sum = 0;
for (var val of values) {
sum += val;
}
return sum;
}
add(2, 5, 3) // 10
function push(array, ...items) {
items.forEach(function(item) {
array.push(item);
console.log(item);
});
}
var a = [];
push(a, 1, 2, 3)

四、扩展运算符(…)

它好比 rest 参数的逆运算,将一个数组转为用逗号分隔的参数序列。
扩展运算符内部调用的是数据结构的Iterator接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
console.log(...[1, 2, 3])
// 1 2 3
console.log(1, ...[2, 3, 4], 5)
// 1 2 3 4 5
[...document.querySelectorAll('div')]
// [<div>, <div>, <div>]
function push(array, ...items) {
array.push(...items);
}
function add(x, y) {
return x + y;
}
let numbers = [4, 38];
add(...numbers) // 42

栗子:

  • 替代数组的apply方法
1
2
3
4
5
6
// ES5的写法
Math.max.apply(null, [14, 3, 77])
// ES6的写法
Math.max(...[14, 3, 77])
// 等同于
Math.max(14, 3, 77);
  • 合并数组
1
2
3
4
5
6
7
8
9
10
11
12
13
// ES5
[1, 2].concat(more)
// ES6
[1, 2, ...more]
var arr1 = ['a', 'b'];
var arr2 = ['c'];
var arr3 = ['d', 'e'];
// ES5的合并数组
arr1.concat(arr2, arr3);
// [ 'a', 'b', 'c', 'd', 'e' ]
// ES6的合并数组
[...arr1, ...arr2, ...arr3]
// [ 'a', 'b', 'c', 'd', 'e' ]
  • 与解构赋值结合
1
2
3
4
5
6
7
8
9
const [first, ...rest] = [1, 2, 3, 4, 5];
first // 1
rest // [2, 3, 4, 5]
const [first, ...rest] = [];
first // undefined
rest // []:
const [first, ...rest] = ["foo"];
first // "foo"
rest // []

五、箭头函数

箭头函数可以让this指向固定化,这种特性很有利于封装回调函数

(1)函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象。

(2)不可以当作构造函数,也就是说,不可以使用new命令,否则会抛出一个错误。

(3)不可以使用arguments对象,该对象在函数体内不存在。如果要用,可以用Rest参数代替。

(4)不可以使用yield命令,因此箭头函数不能用作Generator函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
var f = () => 5;
// 等同于
var f = function () { return 5 };
var f = v => v;
//等同于:
var f = function(v) {
return v;
};
var sum = (num1, num2) => num1 + num2;
// 等同于
var sum = function(num1, num2) {
return num1 + num2;
};
  • 箭头函数简化回调函数
1
2
3
4
5
6
// 正常函数写法
[1,2,3].map(function (x) {
return x * x;
});
// 箭头函数写法
[1,2,3].map(x => x * x);
  • 箭头函数可以让setTimeout里面的this,绑定定义时所在的作用域,而不是指向运行时所在的作用域
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function Timer() {
this.s1 = 0;
this.s2 = 0;
// 箭头函数
setInterval(() => this.s1++, 1000);
// 普通函数
setInterval(function () {
this.s2++;
}, 1000);
}
var timer = new Timer();
setTimeout(() => console.log('s1: ', timer.s1), 3100);
setTimeout(() => console.log('s2: ', timer.s2), 3100);
// s1: 3
// s2: 0
  • 因为所有的内层函数都是箭头函数,都没有自己的this,它们的this其实都是最外层foo函数的this
1
2
3
4
5
6
7
8
9
10
11
12
13
function foo() {
return () => {
return () => {
return () => {
console.log('id:', this.id);
};
};
};
}
var f = foo.call({id: 1});
var t1 = f.call({id: 2})()(); // id: 1
var t2 = f().call({id: 3})(); // id: 1
var t3 = f()().call({id: 4}); // id: 1

Github地址: https://github.com/hzzly/learn-es6