箭头函数与普通函数区别
大约 3 分钟
箭头函数与普通函数的区别
1. this 指向的不同
普通函数:this 的值取决于函数如何被调用
// 普通函数
function normalFunction() {
console.log(this);
}
const obj = {
name: "对象",
method: function() {
console.log(this.name); // this 指向 obj
// 内部函数
function innerFunction() {
console.log(this); // this 指向全局对象 (非严格模式) 或 undefined (严格模式)
}
innerFunction();
}
};
normalFunction(); // this 指向全局对象
obj.method(); // this 指向 obj箭头函数:this 继承自外层作用域(词法作用域)
const obj = {
name: "对象",
method: function() {
// 箭头函数继承外层的 this
const arrowFunction = () => {
console.log(this.name); // this 指向 obj
};
arrowFunction();
}
};
obj.method(); // 输出: "对象"
// 事件处理中的应用
class Button {
constructor(element) {
this.element = element;
this.clickCount = 0;
// 使用箭头函数,this 指向 Button 实例
this.element.addEventListener('click', () => {
this.clickCount++;
console.log(`点击了 ${this.clickCount} 次`);
});
}
}2. arguments 对象
普通函数:拥有自己的 arguments 对象
function normalFunc() {
console.log(arguments); // 包含所有传入的参数
}
normalFunc(1, 2, 3); // Arguments(3) [1, 2, 3, ...]箭头函数:没有自己的 arguments 对象
const arrowFunc = () => {
// console.log(arguments); // ReferenceError: arguments is not defined
// 可以使用 rest 参数替代
};
// 如果需要访问参数,可以使用 rest 参数
const arrowFuncWithRest = (...args) => {
console.log(args); // [1, 2, 3]
};
arrowFuncWithRest(1, 2, 3);3. 构造函数能力
普通函数:可以用作构造函数
function Person(name) {
this.name = name;
}
const person = new Person("张三");
console.log(person.name); // "张三"箭头函数:不能用作构造函数
const ArrowPerson = (name) => {
this.name = name;
};
// const person = new ArrowPerson("张三"); // TypeError: ArrowPerson is not a constructor4. 原型属性
普通函数:有 prototype 属性
function NormalFunc() {}
console.log(NormalFunc.prototype); // { constructor: ... }箭头函数:没有 prototype 属性
const arrowFunc = () => {};
console.log(arrowFunc.prototype); // undefined5. 生成器能力
普通函数:可以定义生成器函数
function* generatorFunc() {
yield 1;
yield 2;
}
const gen = generatorFunc();
console.log(gen.next()); // { value: 1, done: false }箭头函数:不能定义生成器
// const arrowGenerator = *() => { // SyntaxError
// yield 1;
// };使用箭头函数需要注意的事项
1. 不要将箭头函数用作对象方法
// 错误用法
const obj = {
name: "对象",
// 这里的 this 不指向 obj
getName: () => {
return this.name; // undefined
}
};
console.log(obj.getName()); // undefined
// 正确用法
const obj2 = {
name: "对象",
// 使用普通函数
getName: function() {
return this.name; // "对象"
},
// 或者使用简写方法
getName2() {
return this.name; // "对象"
}
};2. 箭头函数不能用 call、apply、bind 改变 this
const obj1 = { name: "对象1" };
const obj2 = { name: "对象2" };
function normalFunc() {
return this.name;
}
const arrowFunc = () => {
return this.name;
};
console.log(normalFunc.call(obj1)); // "对象1"
console.log(normalFunc.call(obj2)); // "对象2"
// 箭头函数的 this 不会改变
console.log(arrowFunc.call(obj1)); // undefined (取决于外层作用域的 this)
console.log(arrowFunc.call(obj2)); // undefined (取决于外层作用域的 this)3. 在类中的使用注意事项
class Counter {
constructor() {
this.count = 0;
}
// 普通方法
increment() {
this.count++;
}
// 箭头方法 - this 绑定到实例
decrement = () => {
this.count--;
}
// 普通方法中的定时器
startTimerNormal() {
setTimeout(function() {
// this 指向全局对象,不是 Counter 实例
// this.count++; // 错误!
}, 1000);
}
// 箭头函数中的定时器
startTimerArrow() {
setTimeout(() => {
// this 继承自外层,指向 Counter 实例
this.count++; // 正确!
}, 1000);
}
}4. DOM 事件处理中的应用
class EventHandler {
constructor() {
this.clickCount = 0;
this.init();
}
init() {
const button = document.getElementById('myButton');
// 错误:普通函数,this 不指向实例
// button.addEventListener('click', function() {
// this.clickCount++; // this 指向 button 元素
// });
// 正确:箭头函数,this 指向 EventHandler 实例
button.addEventListener('click', () => {
this.clickCount++;
console.log(`点击次数: ${this.clickCount}`);
});
}
}5. 数组方法中的使用
class NumberProcessor {
constructor(multiplier) {
this.multiplier = multiplier;
}
processNumbers(numbers) {
// 使用箭头函数可以访问 this.multiplier
return numbers.map(num => num * this.multiplier);
}
filterEvenNumbers(numbers) {
// 箭头函数中的 this 指向 NumberProcessor 实例
return numbers.filter(num => num % 2 === 0 && num > this.multiplier);
}
}
const processor = new NumberProcessor(2);
console.log(processor.processNumbers([1, 2, 3, 4])); // [2, 4, 6, 8]
console.log(processor.filterEvenNumbers([1, 2, 3, 4, 5, 6])); // [4, 6]总结
箭头函数的主要优势在于简洁的语法和词法 this 绑定,特别适用于回调函数和数组方法。但在需要动态 this 绑定、作为构造函数或对象方法的场景中,应该使用普通函数。