本文详细解析ES6箭头函数的定义语法、参数处理、代码块写法及对象返回规则。重点阐述箭头函数this静态绑定特性,说明其作为构造函数、arguments对象及Generator函数的限制。通过实例对比,明确定义方法内部含this及事件监听等动态this场景下应避免使用箭头函数,并提供Rest参数结合使用的技巧。
箭头函数基本语法与定义
本文详细介绍ES6中箭头函数的具体用法,旨在为读者提供清晰的参考与指导。
ES6标准引入了“箭头”(=>)符号来定义函数,使函数定义更加简洁。
var f = v => v
// 等同于
var f = function(v) {
return v
}
当箭头函数无需参数或包含多个参数时,需在参数部分使用圆括号进行包裹。
var f = () => 5
// 等同于
var f = function() {
return 5
}
var sum = (num1, num2) => num1 + num2
// 等同于
var sum = function(num1, num2) {
return num1 + num2
}
若箭头函数的主体包含多条语句,必须使用大括号将代码块括起,并显式使用return语句返回结果。
var sum = (num1, num2) => {return num1 + num2}
由于大括号在箭头函数中被解析为代码块,若希望直接返回一个对象,必须在对象外层添加括号,否则会导致语法错误。
// 报错
let getTempItem = id => {id: id, name: "Temp"}
// 不报错
let getTempItem = id => ({id: id, name: "Temp"})
存在一种特殊情况,代码虽能运行,但结果可能不符合预期。
let foo = () => {a: 1}
上述代码中,开发者意图返回对象{a: 1},但引擎将大括号视为代码块,执行语句a: 1。此时a被视为标签,实际执行的是数值1,函数因此无返回值。
若箭头函数仅包含一条语句且无需返回值,可采用省略大括号的写法。
let fn = () => void doesNotReturn()
箭头函数支持与变量解构语法结合使用。
const full = ({first, last}) => first + ' ' + last
// 等同于
function full(person) {
return person.first + ' ' + person.last
}
使用箭头函数可使代码表达更为简洁明了。
const isEven = n => n % 2 === 0
const square = n => n * n
箭头函数的一个常见应用场景是简化回调函数的编写。
// 正常函数写法
[1, 2, 3].map(function(x) {
return x * x
})
// 箭头函数写法
[1, 2, 3].map(x => x * x)
以下是Rest参数与箭头函数结合使用的示例。
const numbers = (...nums) => nums
numbers(1, 2, 3, 4, 5)
const headAndTail = (head, ...tail) => [head, tail]
headAndTail(1, 2, 3, 4, 5)
箭头函数的使用注意点
使用箭头函数时需注意以下关键点:
1)函数体内的this对象继承自定义时所在的对象,而非调用时的对象。 2) 不可作为构造函数使用,即不能配合new命令,否则将抛出错误。 3)函数体内不存在arguments对象,如需使用,可借助Rest参数替代。 4)不支持yield命令,因此不能用于定义Generator函数。
function foo () {
setTimeout(() => {
console.log('id: ', this.id)
}, 100)
}
var id = 21
foo.call({id: 42})
示例中,setTimeout的参数为箭头函数,该函数在foo函数生成时定义,实际执行延迟至100ms后。若为普通函数,执行时this指向全局对象window,预期输出21。然而,箭头函数使this始终指向定义生效时的对象,故输出结果为42。
箭头函数自身不拥有this,其内部的this直接指向外层代码块的this。正因缺乏独立的this,箭头函数无法用作构造函数。
除this外,以下三个变量在箭头函数内部同样不可用:
arguments, super, new.target
此外,由于箭头函数没有自己的this,因此无法使用call()、apply()或bind()方法来改变其this指向。
(function() {
return [
(() => this.x).bind({x: 'inner'})()
]
}).call({x: 'outer'})
箭头函数的不适用场合
在以下场合中,不建议使用箭头函数:
由于箭头函数将this从“动态”变为“静态”,以下两种场景应避免使用。
第一种场景是定义包含this的方法时。
window.lives = 100
var cat = {
lives: 9,
jumps: () => { this.lives--; console.log(this.lives)}
}
// 99
示例中,cat.jumps()方法若定义为箭头函数,则属错误写法。调用时,若为普通函数,this指向cat;若为箭头函数,this指向全局对象,导致结果非预期。
第二种场景是需要在事件监听中动态获取this时,也不宜使用箭头函数。
var button = document.getElementById('press');
button.addEventListener('click', () => {
this.classList.toggle('on');
});
示例运行时,点击按钮会报错。因为监听函数为箭头函数,其内部this指向全局对象。若改为普通函数,this将动态指向被点击的按钮对象。
感兴趣的用户可使用在线HTML/CSS/JavaScript代码运行工具:http://tools.jb51.net/code/HtmlJsRun测试上述代码的运行效果。
更多关于JavaScript的内容,可参考本站专题:《JavaScript常用函数技巧汇总》、《javascript面向对象入门教程》、《JavaScript错误与调试技巧总结》、《JavaScript数据结构与算法技巧总结》及《JavaScript数学运算用法总结》。
希望本文所述内容能对JavaScript程序设计有所帮助。