在本教程中,您将学习如何使用 JavaScript 箭头函数为函数表达式编写更简洁的代码。
JavaScript 箭头函数介绍
与函数表达式相比,ES6 箭头函数为您提供一种编写更短的语法。
下面的示例定义一个返回两个数字之和的函数表达式:
let add = function (x, y) {
return x + y;
};
console.log(add(10, 20)); // 30
下面的示例等效于上述函数表达式 add()
,但使用箭头函数代替:
let add = (x, y) => x + y;
console.log(add(10, 20)); // 30;
在这个例子中,箭头函数有一个表达式 x + y
,它将返回表达式的结果。
但是,如果使用函数体语法,则需要指定 return
关键字:
let add = (x, y) => { return x + y; };
运算符 typeof
返回指示箭头函数的类型是 function
。
console.log(typeof add); // function
箭头函数也是 Function 类型的一个实例,如下所示:
console.log(add instanceof Function); // true
多个参数的 JavaScript 箭头函数
如果箭头函数有两个或多个参数,则使用以下语法:
(p1, p2, ..., pn) => expression;
下面的表达式:
=> expression
等同于以下表达式:
=> { return expression; }
例如,要按降序对数字数组进行排序,可以使用数组对象的 sort()
方法,如下所示:
let numbers = [4,2,6];
numbers.sort(function(a,b){
return b - a;
});
console.log(numbers); // [6,4,2]
上面的代码使用箭头函数使语法更加简洁:
let numbers = [4,2,6];
numbers.sort((a,b) => b - a);
console.log(numbers); // [6,4,2]
单个参数的 JavaScript 箭头函数
如果箭头函数采用单个参数,则使用以下语法:
(p1) => { statements }
您也可以省略括号,如下所示:
p => { statements }
下面的示例使用箭头函数作为数组的 map()
方法的参数将字符串数组转换为字符串长度。
let names = ['John', 'Mac', 'Peter'];
let lengths = names.map(name => name.length);
console.log(lengths);
输出:
[ 4, 3, 5 ]
没有参数的 JavaScript 箭头函数
如果箭头函数没有参数,则需要使用括号,如下所示:
() => { statements }
例如:
let logDoc = () => console.log(window.document);
logDoc();
参数定义和箭头之间的换行符
JavaScript 不允许在箭头函数的参数定义和箭头 ( =>
) 之间使用换行符。
例如,下面的代码会导致语法错误 SyntaxError
:
let multiply = (x,y)
=> x * y;
但是,下面的代码工作得很好:
let multiply = (x,y) =>
x * y;
JavaScript 允许您在参数之间使用换行符,如下例所示:
let multiply = (
x,
y
) =>
x * y;
箭头函数体的语句和表达式
在 JavaScript ,表达式的计算结果如下例所示。
10 + 20;
语句执行指定的任务,例如:
if (x === y) {
console.log('x equals y');
}
如果在箭头函数的主体使用表达式,则不需要使用花括号。
let square = x => x * x;
但是,如果您使用语句,则必须将其括在一对大括号内,如下例所示:
let except = msg => {
throw msg;
};
JavaScript 箭头函数和对象字面量
考虑以下示例:
let setColor = function (color) {
return {value: color}
};
let backgroundColor = setColor('Red');
console.log(backgroundColor.value); // "Red"
函数 setColor()
表达式返回一个对象,将 value
属性设置为 color
参数的。
如果使用以下语法从箭头函数返回对象字面量,则会出现错误。
p => {object:literal}
例如,以下代码会导致错误。
let setColor = color => {value: color };
由于块 {}
和对象字面量都使用大括号,因此 JavaScript 引擎无法区分块 {}
和对象。
要解决此问题,您需要将对象字面量括在括号中,如下所示:
let setColor = color => ({value: color });
箭头函数与普通函数
箭头函数和普通函数之间有两个主要区别。
- 首先,在箭头函数,
this
,arguments
,super
,new.target
是词法。这意味着箭头函数使用封闭作用域内的这些变量。 - 其次,箭头函数不能用作函数构造函数。如果你使用
new
关键字从箭头函数创建一个新对象,你会得到一个错误。
JavaScript 箭头函数与 this 值
在 JavaScript ,一个新函数定义了它自己的 this
值。但是,箭头函数并非如此。请阅读以下示例:
function Car() {
this.speed = 0;
this.speedUp = function (speed) {
this.speed = speed;
setTimeout(function () {
console.log(this.speed); // undefined
}, 1000);
};
}
let car = new Car();
car.speedUp(50);
在 setTimeout()
函数的匿名函数内部,this.speed
是 undefined
, 原因是匿名函数的 this
隐藏 speedUp()
方法的 this
。
要解决此问题,您可以将 this
值分配给一个不隐藏在匿名函数内部的变量,如下所示:
function Car() {
this.speed = 0;
this.speedUp = function (speed) {
this.speed = speed;
let self = this;
setTimeout(function () {
console.log(self.speed);
}, 1000);
};
}
let car = new Car();
car.speedUp(50); // 50;
与匿名函数不同,箭头函数捕获封闭上下文的 this
值,而不是创建自己的 this
上下文。下面的代码应按预期工作:
function Car() {
this.speed = 0;
this.speedUp = function (speed) {
this.speed = speed;
setTimeout(
() => console.log(this.speed),
1000);
};
}
let car = new Car();
car.speedUp(50); // 50;
JavaScript 箭头函数和 arguments 参数对象
箭头函数没有 arguments
对象 。例如:
function show() {
return x => x + arguments[0];
}
let display = show(10, 20);
let result = display(5);
console.log(result); // 15
showMe()
函数内部的箭头函数引用 arguments
对象。但是,这个 arguments
对象属于 show()
函数,不属于箭头函数。
此外,箭头函数没有关键字new.target
。
JavaScript 箭头函数和原型属性
当您使用关键字 function
定义函数时,函数有一个名为 prototype
的属性:
function dump( message ) {
console.log(message);
}
console.log(dump.hasOwnProperty('prototype')); // true
但是,箭头函数没有 prototype
属性:
let dump = message => console.log(message);
console.log(dump.hasOwnProperty('prototype')); // false
将箭头函数用于回调和闭包是最佳实践,因为箭头函数的语法更清晰。
结论
- 使用
(...args) => expression;
来定义箭头函数。 - 使用
(...args) => { statements }
来定义具有多个语句的箭头函数。 - 箭头函数没有自己的
this
与super
。 - 箭头函数没有
arguments
对象、new.target
关键字和prototype
属性。