箭头函数

箭头函数语法

箭头函数是ES6引入的一种更简洁的函数语法。

基本语法

// 传统函数
function add(a, b) {
    return a + b;
}

// 箭头函数
const add = (a, b) => {
    return a + b;
};

// 简写:单行表达式自动返回
const add = (a, b) => a + b;

参数形式

// 无参数
const greet = () => console.log("你好!");

// 单个参数(可省略括号)
const double = x => x * 2;

// 多个参数
const add = (a, b) => a + b;

// 带默认值
const greet = (name = "访客") => `你好,${name}!`;

// 剩余参数
const sum = (...numbers) => numbers.reduce((a, b) => a + b, 0);

函数体形式

// 表达式体(自动返回)
const square = x => x * x;

// 块体(需要显式return)
const calculate = (a, b) => {
    const sum = a + b;
    const product = a * b;
    return { sum, product };
};

// 返回对象字面量(需要括号)
const createUser = (name, age) => ({ name, age });

语法对比

// 传统函数
const traditional = function(x) {
    return x * 2;
};

// 箭头函数完整形式
const arrow1 = (x) => {
    return x * 2;
};

// 箭头函数简写形式
const arrow2 = x => x * 2;

箭头函数特性

箭头函数与传统函数有几个重要区别。

没有自己的this

// 传统函数的this
const obj1 = {
    name: "东巴文",
    greet: function() {
        console.log(this.name);  // "东巴文"
        
        setTimeout(function() {
            console.log(this.name);  // undefined(严格模式)
        }, 100);
    }
};

// 箭头函数继承this
const obj2 = {
    name: "东巴文",
    greet: function() {
        console.log(this.name);  // "东巴文"
        
        setTimeout(() => {
            console.log(this.name);  // "东巴文"(继承外层this)
        }, 100);
    }
};

没有arguments对象

// 传统函数有arguments
function traditional() {
    console.log(arguments);  // Arguments对象
}

// 箭头函数没有arguments
const arrow = () => {
    console.log(arguments);  // ReferenceError
};

// 使用剩余参数替代
const arrow2 = (...args) => {
    console.log(args);  // 数组
};

不能用作构造函数

// 传统函数可以用new
function Person(name) {
    this.name = name;
}
const p1 = new Person("东巴文");  // 正常

// 箭头函数不能用new
const Person = (name) => {
    this.name = name;
};
const p2 = new Person("东巴文");  // TypeError

没有prototype属性

function traditional() {}
console.log(traditional.prototype);  // { constructor: f }

const arrow = () => {};
console.log(arrow.prototype);  // undefined

不能用作Generator

// 传统函数可以是generator
function* generator() {
    yield 1;
}

// 箭头函数不能是generator
const generator = *() => {  // SyntaxError
    yield 1;
};

this绑定

箭头函数的this是词法绑定的。

this继承规则

const obj = {
    name: "东巴文",
    
    // 方法中的箭头函数
    greet: function() {
        const arrow = () => {
            console.log(this.name);  // 继承greet的this
        };
        arrow();
    },
    
    // 箭头函数作为方法(不推荐)
    sayHi: () => {
        console.log(this.name);  // undefined(继承全局this)
    }
};

obj.greet();  // "东巴文"
obj.sayHi();  // undefined

常见应用场景

// 回调函数
const button = {
    clicked: false,
    click: function() {
        this.clicked = true;
        
        document.addEventListener("click", () => {
            console.log(this.clicked);  // true(继承this)
        });
    }
};

// 数组方法回调
const obj = {
    numbers: [1, 2, 3],
    double: function() {
        return this.numbers.map(n => n * this.multiplier);
    },
    multiplier: 2
};

// 定时器
function Timer() {
    this.seconds = 0;
    setInterval(() => {
        this.seconds++;
        console.log(this.seconds);
    }, 1000);
}

this绑定对比

const obj = {
    name: "东巴文",
    
    // 传统函数需要bind
    traditional: function() {
        [1, 2, 3].forEach(function(n) {
            console.log(this.name, n);  // undefined
        });
    },
    
    traditionalBound: function() {
        [1, 2, 3].forEach(function(n) {
            console.log(this.name, n);  // "东巴文"
        }.bind(this));
    },
    
    // 箭头函数自动绑定
    arrow: function() {
        [1, 2, 3].forEach(n => {
            console.log(this.name, n);  // "东巴文"
        });
    }
};

箭头函数限制

箭头函数在某些场景下不适用。

不适合作为对象方法

const obj = {
    name: "东巴文",
    
    // 不推荐
    greet: () => {
        console.log(this.name);  // undefined
    },
    
    // 推荐
    greet2: function() {
        console.log(this.name);  // "东巴文"
    },
    
    // 或使用方法简写
    greet3() {
        console.log(this.name);  // "东巴文"
    }
};

不适合作为构造函数

// 不能用new
const Person = (name) => {
    this.name = name;
};

new Person("东巴文");  // TypeError

// 使用传统函数或class
class Person {
    constructor(name) {
        this.name = name;
    }
}

不适合需要arguments的场景

// 需要arguments时用传统函数
function flexible() {
    console.log(arguments);
}

// 或使用剩余参数
const flexible2 = (...args) => {
    console.log(args);
};

不适合动态this

// 需要动态this的场景
const button = document.querySelector("button");

// 传统函数:this指向button
button.addEventListener("click", function() {
    this.classList.add("active");  // this是button
});

// 箭头函数:this不指向button
button.addEventListener("click", () => {
    this.classList.add("active");  // this不是button
});

箭头函数应用场景

数组方法

const numbers = [1, 2, 3, 4, 5];

// map
const doubled = numbers.map(n => n * 2);

// filter
const evens = numbers.filter(n => n % 2 === 0);

// reduce
const sum = numbers.reduce((a, b) => a + b, 0);

// find
const found = numbers.find(n => n > 3);

// some
const hasEven = numbers.some(n => n % 2 === 0);

// every
const allPositive = numbers.every(n => n > 0);

Promise链

fetch("/api/users")
    .then(response => response.json())
    .then(users => users.filter(u => u.active))
    .then(active => console.log(active))
    .catch(error => console.error(error));

async/await

const fetchData = async () => {
    try {
        const response = await fetch("/api/data");
        const data = await response.json();
        return data;
    } catch (error) {
        console.error(error);
    }
};

回调函数

// 定时器
setTimeout(() => {
    console.log("延迟执行");
}, 1000);

// 事件监听
element.addEventListener("click", (event) => {
    console.log("点击事件", event.target);
});

// 数组排序
const users = [
    { name: "东巴文", age: 1 },
    { name: "JavaScript", age: 27 }
];
users.sort((a, b) => a.age - b.age);

解构参数

// 对象解构
const display = ({ name, age }) => `${name}, ${age}岁`;
display({ name: "东巴文", age: 1 });

// 数组解构
const getCoords = ([x, y]) => ({ x, y });
getCoords([10, 20]);

// 带默认值
const greet = ({ name = "访客" } = {}) => `你好,${name}`;
greet();  // "你好,访客"

箭头函数最佳实践

推荐使用场景

// 数组方法回调
items.map(item => item.value);

// Promise链
promise.then(value => process(value));

// 简单的工具函数
const double = x => x * 2;

// 需要继承外层this的回调
class Timer {
    start() {
        setInterval(() => this.tick(), 1000);
    }
}

不推荐使用场景

// 对象方法
const obj = {
    // 不推荐
    method: () => { },
    // 推荐
    method() { }
};

// 构造函数
// 不推荐
const Person = (name) => { };
// 推荐
function Person(name) { }
// 或
class Person { }

// 需要arguments
// 不推荐
const fn = () => arguments;
// 推荐
const fn = (...args) => args;

// 需要动态this
element.addEventListener("click", function() {
    this.classList.add("active");
});

下一步

掌握了箭头函数后,让我们继续学习:

  1. 作用域与闭包 - 学习作用域
  2. 高阶函数 - 学习高阶函数
  3. this与执行上下文 - 深入理解this

东巴文(db-w.cn) - 让编程学习更简单

➡️ 东巴文寄语:箭头函数是ES6最重要的特性之一,简洁的语法和词法this让它成为现代JavaScript开发的首选。但要注意它的限制,在合适的场景使用。在 db-w.cn,我们帮你掌握每一个细节!