ES6学习笔记(2):函数
参考资料 深入理解ES6 Zakas著
箭头函数
特性
- 没有
this
、super
、arguments
、new.target
绑定 - 不能通过
new
关键字调用 - 没有原型
- 不可改变
this
绑定 - 不支持
arguments
对象 - 不支持重复的命名参数
语法
//single param, return single expression 单个参数,返回单一表达式
let reflect = value => value;
//is equal to 相当于
let reflect = function (value) {
return value;
}
/****************************************************************************/
//multiple params, return single expression 多参数,返回单一表达式
let sum = (num1, num2) => num1 + num2;
/****************************************************************************/
//no param, return single expression 无参数,返回单一表达式
let getName = () => "Damian";
/****************************************************************************/
//multiple expressions 多表达式函数体
let sum = (num1, num2) => {
return num1 + num2;
}
/****************************************************************************/
//return JSON 返回对象字面量,或JSON
let getTempItem = id => ({
id: id,
name: "Temp"
});
/****************************************************************************/
//IIFE 立即调用函数表达式
let person = ((name) => {
return {
getName: () => name
}
})("Damian");
console.log(person.getName());
1、箭头函数没有this
绑定,箭头函数内的this
为最近一层非箭头函数的this
,所以this
也可能指向全局对象
//这样写会出问题
let person = {
name: "Damian",
getName: () => this.name,
isThisEqualToWindow: () => {
console.log(this === window);//1
}
}
console.log(person.getName()); //undefine
person.isThisEqualToWindow(); //true
语句1
中的this
没有外层非箭头函数,所以指向的是全局对象。
下面是书中提供的用法:
//正确用法
let PageHandler = {
id: "123456",
init: function () {
document.addEventListener("click", event => this.doSomething(event.type), false);//1
},
doSomething: function (type) {
console.log("Handling " + type + " for " + this.id);//2
}
};
PageHandler.init();
在语句1
中,this
的外层非箭头函数是init
,而调用init
的对象是PageHandler
,所以this
指向PageHandler
。
语句2
中的this
同样指向PageHandler
。
2、箭头函数没有arguments
绑定,arguments
为外层函数的arguments
。
function outer(arg) {
return () => arguments[0];
}
var func = outer(123);
console.log(func());//123
默认参数
1、将命名参数写作如first = 0
的形式设置默认参数。
2、函数调用时,未传入相应参数时,将相应参数视作undefined
,此时启用默认参数。
3、函数调用的参数顺序是与定义中的参数对应的,即不能跳过某个参数。可以用undefined
使用默认参数。
function testFunc(first = 0, second = 1, third = function () {
return 2;
}) {
console.log(first + second + third());
}
testFunc();
testFunc(1);
testFunc(undefined, 3, function () {
return 2;
});
output:
- 3
- 4
- 5
4、改变first
和second
不会同时改变arguments
,arguments
保留了初始值。
function testFunc(first, second = "b") {
console.log(arguments.length);
console.log(first === arguments[0]);
console.log(second === arguments[1]);
first = "c";
second = "d";
console.log(first === arguments[0]);
console.log(second === arguments[1]);
}
testFunc("a");
output:
- 1
- true
- false
- false
- false
5、只有在函数调用的时候才计算默认参数值。
let value = 0;
function getValue() {
return value++;
}
function add(first, second = getValue()) {
return first + second;
}
console.log(add(1, 1));
console.log(add(1));
console.log(add(1));
output:
- 2
- 1
- 2
6、趣味儿顺序靠前的命名参数可以被之后的默认参数使用。
function testFunc(first, second = first + 1) {
return first + second;
}
console.log(testFunc(1, 1));
console.log(testFunc(1));
output:
- 2
- 3
不定参数
1、在函数的命名参数前添加三个点...keys
,这就是不定参数,该参数为一个数组,包含自它之后的所有参数。
2、函数定义时,不定参数之后不允许再声明参数(不定参数放在所有参数的末尾)。
3、不定参数不能在setter
中使用。
function pick(first, ...keys) {
let result = first;
for (let i = 0, len = keys.length; i < len; i++) {
result += keys[i];
}
return result;
}
console.log(pick(1, 2, 3, 4));
output:
- 10
4、无论是否使用不定参数, arguments
对象总是包含所有传入函数的参数。
展开运算符
1、在参数数组前面加三个点...args
2、把数组展开为各自独立的参数
function add(...keys) {
let result = 0;
for (let i = 0, len = keys.length; i < len; i++) {
result += keys[i];
}
return result;
}
console.log(add(1, 2, 3, 4));
let arr = [1, 2, 3, 4];
console.log(add(...arr));
let arr2 = [2, 3, 4];
console.log(add(1, ...arr2));
let arr3 = [1, 2, 3];
console.log(add(...arr3, 4));
output:
- 10
- 10
- 10
- 10