箭头函数与普通函数的区别
Arrow Functions: 箭头函数表达式 - JavaScript | MDN
- 箭头函数没有独立的 this、arguments 和 super 绑定,并且不可被用作方法。
- 箭头函数不能用作构造函数。使用 new 调用它们会引发 TypeError。它们也无法访问 new.target 关键字。
- 箭头函数不能在其主体中使用 yield,也不能作为生成器函数创建。
不能用作方法(this
)
箭头函数表达式只能用于非方法函数,因为它们没有自己的 this
。让我们看看将它们用作方法时会发生什么:
"use strict";
const obj = {
i: 10,
b: () => console.log(this.i, this),
c() {
console.log(this.i, this);
},
};
obj.b(); // 输出 undefined, Window { /* … */ }(或全局对象)
obj.c(); // 输出 10, Object { /* … */ }
另外一个示例涉及到 Object.defineProperty()
:
"use strict";
const obj = {
a: 10,
};
Object.defineProperty(obj, "b", {
get: () => {
console.log(this.a, typeof this.a, this); // undefined 'undefined' Window { /* … */ }(或全局对象)
return this.a + 10; // 代表全局对象 'Window',故 `this.a' 返回 'undefined'
},
});
由于类体具有 this
上下文,因此作为类字段的箭头函数会关闭类的 this
上下文,箭头函数体中的 this
将正确指向实例(对于静态字段来说是类本身)。 但是,由于它是一个闭包,而不是函数本身的绑定,因此 this
的值不会根据执行上下文而改变。
class C {
a = 1;
autoBoundMethod = () => {
console.log(this.a);
};
}
const c = new C();
c.autoBoundMethod(); // 1
const { autoBoundMethod } = c;
autoBoundMethod(); // 1
// 如果这是普通方法,此时应该是 undefined
箭头函数属性通常被称作“自动绑定方法”,因为它与普通方法的等价性相同:
class C {
a = 1;
constructor() {
this.method = this.method.bind(this);
}
method() {
console.log(this.a);
}
}
备注: 类字段是在实例(instance)上定义的,而不是在原型(prototype)上定义的,因此每次创建实例都会创建一个新的函数引用并分配一个新的闭包,这可能会导致比普通非绑定方法更多的内存使用。
出于类似原因,call()
、apply()
和 bind()
方法在箭头函数上调用时不起作用,因为箭头函数是根据箭头函数定义的作用域来建立 this
的,而 this
值不会根据函数的调用方式而改变。
没有参数绑定(arguments
)
箭头函数没有自己的 arguments
对象。因此,在本例中,arguments
是对外层作用域参数的引用:
function foo(n) {
const f = () => arguments[0] + n; // foo 的隐式参数绑定。arguments[0] 为 n
return f();
}
foo(3); // 3 + 3 = 6
备注: 在严格模式下不能声明名为
arguments
的变量,因此上面的代码会出现语法错误。这使得arguments
的范围效应更容易理解。
在大多数情况下,使用剩余参数是比使用 arguments
对象更好的选择。
function foo(n) {
const f = (...args) => args[0] + n;
return f(10);
}
foo(1); // 11
不能用作构造函数
箭头函数不能用作构造函数,当使用 new
调用时会出错。它们也没有 `prototype 属性。
const Foo = () => {};
const foo = new Foo(); // TypeError: Foo is not a constructor
console.log("prototype" in Foo); // false
不能用作生成器
箭头函数的主体中不能使用 yield
关键字(除非在箭头函数进一步嵌套的生成器函数中使用)。因此,箭头函数不能用作生成器。