全部 / 前端 / 技术 · 2022年7月10日 0

28 – 箭头函数和 this 关键字

广告位招租 (vx: ghostcode, 备注:网站广告)

原文地址:https://dev.to/bhagatparwinder/arrow-functions-this-keyword-350j

在之前的博文中,我们已经学过了箭头函数和 this 关键字。现在我们将把它俩结合起来并且看看箭头函数与标准的函数表达式行为上有何不同。

箭头函数,多数时候像函数表达式的简写语法。最重要的区别是箭头函数没有和 this 关键字绑定。

对一个函数表达式来说,this 会随着函数调用时的上下文改变。而箭头函数,this 会基于词法作用域。箭头函数遵循普通变量的寻找方式,先在当前作用域中查找 this ,若没有找到则会继续寻找上一层作用域。

我们将会使用上一篇文章的场景:

  1. 直接调用。
  2. 作为构造函数。
  3. 作为对象方法调用。
  4. 在严格模式下使用。
  5. 在事件中使用。

直接调用

const foo = () => {
    return this;
}

console.log(foo()); // window or global object

完全与函数表达式相同。

作为构造函数

const Order = (main, side, dessert) => {
    this.main = main;
    this.side = side;
    this.dessert = dessert;
    this.order = function () {
        return `I will have ${this.main} with ${this.side} and finish off with a ${this.dessert}`;
    }
}
const newOrder = new Order("sushi", "soup", "yogurt"); // Order is not a constructor

console.log(newOrder.order());

箭头函数不能用作构造器。在这个例子中他们表现的不同,虽然将this.order 改为箭头函数,但如果我们不使用箭头函数作为构造函数,效果也是一样的。

function Order(main, side, dessert) {
    this.main = main;
    this.side = side;
    this.dessert = dessert;
    this.order = () => {
        return `I will have ${ this.main } with ${ this.side } and finish off with a ${ this.dessert } `;
    }
}
const newOrder = new Order("sushi", "soup", "yogurt");

console.log(newOrder.order());
// I will have sushi with soup and finish off with a yogurt

作为对象方法调用

const myObject = {
    main: "butter chicken",
    side: "rice",
    dessert: "ice cream",
    order: () => {
        return `I will have ${this.main} with ${this.side} and finish off with ${this.dessert}`;
    }
}

console.log(myObject.order());
// I will have undefined with undefined and finish off with undefined

与函数表达式表现的不同, 作为对象方法时箭头函数不能直接替换函数表达式。

为何 mainsidedessert 的值为 undefined ? 箭头函数内部的 this 指向我们定义对象 myObject 时环境(在这里指向 window)。window 对象上不包含 order 需要的三个变量。

在严格模式下使用

"use strict";
const foo = () => {
    return this;
};

console.log(foo() === undefined); // false
console.log(foo()); // window or global object

与函数表达式表现不同,因为词法作用域中的 this 优先与严格模式下的 this 规则。

在事件中使用

<html lang="en">
<head>
    <meta content="text/html;charset=utf-8" http-equiv="Content-Type">
    <meta content="utf-8" http-equiv="encoding">
</head>
<body>
    <button id="mybutton">
        Click me!
    </button>
    <script>
        var element = document.querySelector("#mybutton");
        element.addEventListener('click', (event) => {
            console.log(this); // window object
            console.log(this.id); // undefined
        }, false);
    </script>
</body>
</html>

与函数表达式表现不同,箭头函数中的 this 是根据定义它的位置决定的,而不是它使用的地方。在这个例子中,我们可以使用 event.currentTarget 来获取元素。

总结:除了自身直接使用,箭头函数表现的与函数表达式有些不同。虽然箭头函数提供了简明的语法和一些优势,但要知道何时不能使用它直接替换函数表达式。