都会用箭头函数,那你知道它有什么缺点,在什么地方不能用吗?

73 阅读2分钟

前言

第一次使用新的Markdown主题(channing-cyan),还挺好看的😋

基础语法

到了2022年,基本上每个前端都能用熟练的使用箭头函数,溜到飞起的那种,它语法简单,能使代码变得更加简洁和清晰(正确使用的情况下),先简单回顾一下箭头函数的语法。

// ES6之前定义函数大概是这样的
const add = function (){};
// 写成箭头函数
const add = () => {};
// 只有一个参数的时候小括号还可以省略(没有参数或大于一个时候不可以省略)
const add = a => {};
// 只有一个返回语句的时候花括号也可以省略
const add = a => a * 2;
// ...

缺点

1、没有arguments

// 普通函数
const fn = function(){
    console.log(arguments) // Arguments(2) [1, 2, callee: ƒ,Symbol(Symbol.iterator): ƒ]
}
fn(1, 2)
// 箭头函数
const fn = () => {
    console.log(arguments) // 报错,arguments is not defined
}
fn(1, 2)

2、无法通过 call apply bind 等改变 this

// 箭头函数的 this 始终指向函数定义时的this,而非执行时。
const fn = () => {
    console.log('this', this) // window
}
fn1.call({ x: 1 })

3、滥用箭头函数会让代码变得难以理解

// ???
const multiply = (a, b) => b === undefined ? b => a * b : a * b

不适用的场景

1、在对象方法中

const obj = {
    name: '小邱',
    getName: () => {
        return this.name // undefined
    }
}
console.log( obj.getName() )

2、在构造函数中

const Person = (name, age) => {
    this.name = name
    this.age = age
}
// 箭头函数内部没有constructor方法,也没有prototype,所以不支持new操作。
const person = new Person('小邱', 18) // 报错 Person is not a constructor

// 注:在ES6 利用class语法定义类时是可以使用箭头函数的
class Foo {
    constructor(name, age) {
        this.name = name
        this.age = age
    }
    getName = () => {
        return this.name
    }
}
const f = new Foo('小邱', 20)
console.log(f.getName()) // 小邱

3、在动态上下文的回调函数中

const btn1 = document.getElementById('btn1')
btn1.addEventListener('click', () => {  
    console.log(this === window) // true
})

4、在Vue中

{
    data() { return { name: '小邱' } },
    methods: {
        getName: () => {
            // 报错 Cannot read properties of undefined (reading 'name')
            return this.name
        },
        // getName() {
        //     return this.name // 正常
        // }
    },
    mounted: () => {
        // 报错 Cannot read properties of undefined (reading 'name')
        console.log('msg', this.name)
    },
    // mounted() {
    //     console.log('msg', this.name) // 正常
    // }
}

5、扩展对象原型

const obj = {
    name: '小邱'
}
obj.__proto__.getName = () => {
    return this.name
}
console.log( obj.getName() ) // undefined

最后

有写的不对,或者有更多箭头函数的缺点和不适用的地方,希望大家能不吝赐教,在下方评论指出,如果这篇文章对你有一点点帮助,希望能得到您的点赞支持。