常问面试内容-箭头函数
. 什么是箭头函数?
箭头函数是ES6中引入的一种新的函数语法,它用更简洁的方式书写函数。
基本语法对比
javascript
// 传统函数写法
function add(a, b) {
return a + b;
}
// 箭头函数写法
const add = (a, b) => {
return a + b;
};
// 更简洁的箭头函数(当只有一条返回语句时)
const add = (a, b) => a + b;
是不是感觉代码简洁了很多?但这只是箭头函数的冰山一角!
2. 箭头函数的基本用法
不同形式的箭头函数
javascript
// 1. 没有参数
const sayHello = () => {
console.log('Hello!');
};
// 2. 一个参数(可以省略括号)
const double = n => n * 2;
// 3. 多个参数
const multiply = (a, b) => a * b;
// 4. 函数体有多条语句
const checkNumber = (num) => {
if (num > 0) {
return '正数';
} else {
return '非正数';
}
};
立即执行的箭头函数
javascript
// 传统立即执行函数
(function() {
console.log('立即执行');
})();
// 箭头函数立即执行
(() => {
console.log('箭头函数立即执行');
})();
3. 箭头函数的核心特性:this绑定
这是箭头函数最重要的特性,也是很多人困惑的地方。
传统函数的this问题
javascript
var name = '全局name';
var obj = {
name: '对象name',
traditionalFunction: function() {
console.log(this.name); // this指向obj
},
showNameLater: function() {
setTimeout(function() {
console.log(this.name); // this指向window!
}, 1000);
}
};
obj.traditionalFunction(); // 输出:'对象name'
obj.showNameLater(); // 输出:'全局name'(不是我们想要的!)
在showNameLater
中,setTimeout里的回调函数有自己的this
,指向了全局对象。
箭头函数解决this问题
javascript
var name = '全局name';
var obj = {
name: '对象name',
showNameLater: function() {
setTimeout(() => {
console.log(this.name); // this继承自showNameLater!
}, 1000);
}
};
obj.showNameLater(); // 输出:'对象name'(正确!)
箭头函数没有自己的this
,它继承外层作用域的this
值。
4. 箭头函数的this绑定规则
规则一:继承外层作用域的this
javascript
function outer() {
return () => {
console.log(this.name);
};
}
var obj1 = { name: 'obj1' };
var obj2 = { name: 'obj2' };
// 箭头函数在定义时确定this
const arrowFunc = outer.call(obj1);
arrowFunc(); // 输出:'obj1'
// 即使尝试用call改变,也不会生效
arrowFunc.call(obj2); // 仍然输出:'obj1'
规则二:在对象方法中的特殊情况
javascript
var name = '全局';
var person = {
name: '张三',
// 传统方法:this指向调用者
traditionalMethod: function() {
console.log(this.name); // 指向person
},
// 箭头函数:this指向定义时的外层作用域
arrowMethod: () => {
console.log(this.name); // 指向全局!
}
};
person.traditionalMethod(); // 输出:'张三'
person.arrowMethod(); // 输出:'全局'
这是因为对象字面量{}
不创建作用域,箭头函数在全局作用域中定义。
5. 箭头函数的其他特性
没有arguments对象
javascript
// 传统函数有arguments
function traditional() {
console.log(arguments);
}
// 箭头函数没有arguments
const arrow = () => {
console.log(arguments); // 错误!
};
// 可以用剩余参数代替
const arrowWithArgs = (...args) => {
console.log(args);
};
不能作为构造函数
javascript
// 传统函数可以作为构造函数
function Person(name) {
this.name = name;
}
const person = new Person('张三'); // 正确
// 箭头函数不能作为构造函数
const Animal = (name) => {
this.name = name;
};
const animal = new Animal('猫'); // 报错!
没有prototype属性
javascript
function traditionalFunc() {}
console.log(traditionalFunc.prototype); // 有prototype
const arrowFunc = () => {};
console.log(arrowFunc.prototype); // undefined
6. 箭头函数的适用场景
适合使用的场景
javascript
// 1. 回调函数
const numbers = [1, 2, 3, 4, 5];
const doubled = numbers.map(n => n * 2);
// 2. 定时器
setTimeout(() => {
console.log('1秒后执行');
}, 1000);
// 3. 事件处理(需要小心,可能不适合所有情况)
button.addEventListener('click', () => {
console.log('按钮被点击');
});
// 4. 在需要固定this的场景
class Counter {
constructor() {
this.count = 0;
}
start() {
setInterval(() => {
this.count++; // this正确指向Counter实例
console.log(this.count);
}, 1000);
}
}
不适合使用的场景
javascript
// 1. 对象方法(需要动态this)
const obj = {
values: [1, 2, 3],
getValue: function(index) {
return this.values[index]; // 需要this指向obj
}
};
// 2. 构造函数
// 箭头函数不能用作构造函数
// 3. 需要arguments对象的函数
function traditional() {
console.log(arguments); // 需要访问arguments
}
8. 总结
特性 | 传统函数 | 箭头函数 |
---|---|---|
this绑定 | 动态绑定 | 词法作用域绑定 |
arguments | 有 | 无 |
构造函数 | 可以 | 不可以 |
prototype | 有 | 无 |
语法 | 相对冗长 | 简洁 |
使用建议:
-
使用箭头函数:回调函数、需要固定this的场景、简单的单行函数
-
使用传统函数:对象方法、构造函数、需要arguments的函数
记住:箭头函数的this在定义时确定,不会改变,这是理解箭头函数的关键