为什么箭头函数必须声明在调用函数之上
Why arrow function has to be declared above the caller function
在 javascript 文件中,当我使用 function
关键字声明函数时,我可以将函数放在调用函数之后,例如
// test.js
function myCaller() {
foo('hello world'); // this works!
this.foo('hello world'); // this works!
}
function foo(text) {
console.log('foo called!', text);
}
myCaller()
但是如果我把foo
变成一个箭头函数,放在同一个位置,那么在myCaller
函数中,它说foo
没有定义,也赢了如果我使用 this
关键字定位 foo
函数,我假设 this
指的是 global/document 级别
// test.js
function myCaller() {
foo('hello world'); // es-lint warning: 'foo' was used before it was defined
this.foo('hello world'); // compilation error: foo is not defined
}
const foo = (text) => {
console.log('foo called!', text);
}
myCaller();
- 我错了,我认为不使用 this
的第二种方法不起作用,因为 not defined
的 javascript 编译错误,但这实际上是我的 eslint 错误 - 'foo' was used before it was defined
,是不是不建议这样做?
为什么会这样,这是否意味着我们必须始终在 caller
函数上方声明箭头函数?有没有其他方法可以解决这个问题?
const foo = (text) => {
console.log('foo called!', text);
}
// test.js
function myCaller() {
foo('hello world'); // this works! no es-lint warning now
this.foo('hello world'); // no compilation error but there is a run-time error : 'this.foo is not a function'
}
myCaller();
此外,我发现当在 javascript class 中声明箭头函数时,它只能与 this
关键字一起使用,如果调用者函数也是箭头函数函数带有 function
关键字,这将不起作用...
// myTest.js
class myTest {
myCaller() {
foo('hello world'); // compilation error: foo is undefined
}
myCaller2 = () => {
this.foo('hello world'); //this works!
}
foo = (text) => {
console.log('foo called!', text);
}
}
new myTest().myCaller();
new myTest().myCaller2();
您声明的任何变量(let
和 const
变量除外)或您在全局上下文中定义的函数(例如,直接在 test.js 中)将附加到 Window 对象。所以,当你写的时候,
// test.js
function myCaller() {
foo('hello world'); // this works!
this.foo('hello world'); // this works!
}
function foo(text) {
console.log('foo called!', text);
}
myCaller()
myCaller
和 foo
都作为属性附加到 window 对象。现在您可以直接引用它们,例如 foo()
(此处隐含)或 this.foo()
甚至 window.foo()
。由于js使用了提升,这些变量或函数先附加到上下文,然后开始执行。
但是 const
和 let
没有附加到 Window 对象(否则它们可以随处访问,表现得与 var
完全一样)。所以当你写
// test.js
function myCaller() {
foo('hello world');
this.foo('hello world');
}
const foo = (text) => {
console.log('foo called!', text);
}
myCaller();
Javascript 引擎扫描整个脚本以查看是否定义了任何变量或函数。在这个提升阶段,如果它找到 const
或 let
,它会为它们分配内存但不会使它们成为 Window 对象的一部分。因此,当您在全局上下文中引用 this
时,它指的是 window 对象,而 foo
不是 window 对象的 属性。这就是为什么,即使你把 const foo
放在 myCaller
定义之上,它也不起作用。
在 class 的情况下,如果您尝试直接调用 foo()
而不引用它,它会尝试从封闭的上下文中访问它,而您的示例中没有定义它。所以它会抛出错误。如果您在 class 之外用 var
定义另一个 foo()
或直接定义为 foo = (text) => ...
,它将起作用。
( this
可能并不总是指全局上下文。函数和 classes 可以有自己的自定义上下文,而 this
会引用该上下文。但是当函数或 classes 没有定义自定义上下文,全局上下文将是 this
关键字将引用的上下文。this
未定义函数和 class在严格模式下是默认的。有几个这样的警告需要考虑。)
在 javascript 文件中,当我使用 function
关键字声明函数时,我可以将函数放在调用函数之后,例如
// test.js
function myCaller() {
foo('hello world'); // this works!
this.foo('hello world'); // this works!
}
function foo(text) {
console.log('foo called!', text);
}
myCaller()
但是如果我把foo
变成一个箭头函数,放在同一个位置,那么在myCaller
函数中,它说foo
没有定义,也赢了如果我使用 this
关键字定位 foo
函数,我假设 this
指的是 global/document 级别
// test.js
function myCaller() {
foo('hello world'); // es-lint warning: 'foo' was used before it was defined
this.foo('hello world'); // compilation error: foo is not defined
}
const foo = (text) => {
console.log('foo called!', text);
}
myCaller();
- 我错了,我认为不使用 this
的第二种方法不起作用,因为 not defined
的 javascript 编译错误,但这实际上是我的 eslint 错误 - 'foo' was used before it was defined
,是不是不建议这样做?
为什么会这样,这是否意味着我们必须始终在 caller
函数上方声明箭头函数?有没有其他方法可以解决这个问题?
const foo = (text) => {
console.log('foo called!', text);
}
// test.js
function myCaller() {
foo('hello world'); // this works! no es-lint warning now
this.foo('hello world'); // no compilation error but there is a run-time error : 'this.foo is not a function'
}
myCaller();
此外,我发现当在 javascript class 中声明箭头函数时,它只能与 this
关键字一起使用,如果调用者函数也是箭头函数函数带有 function
关键字,这将不起作用...
// myTest.js
class myTest {
myCaller() {
foo('hello world'); // compilation error: foo is undefined
}
myCaller2 = () => {
this.foo('hello world'); //this works!
}
foo = (text) => {
console.log('foo called!', text);
}
}
new myTest().myCaller();
new myTest().myCaller2();
您声明的任何变量(let
和 const
变量除外)或您在全局上下文中定义的函数(例如,直接在 test.js 中)将附加到 Window 对象。所以,当你写的时候,
// test.js
function myCaller() {
foo('hello world'); // this works!
this.foo('hello world'); // this works!
}
function foo(text) {
console.log('foo called!', text);
}
myCaller()
myCaller
和 foo
都作为属性附加到 window 对象。现在您可以直接引用它们,例如 foo()
(此处隐含)或 this.foo()
甚至 window.foo()
。由于js使用了提升,这些变量或函数先附加到上下文,然后开始执行。
但是 const
和 let
没有附加到 Window 对象(否则它们可以随处访问,表现得与 var
完全一样)。所以当你写
// test.js
function myCaller() {
foo('hello world');
this.foo('hello world');
}
const foo = (text) => {
console.log('foo called!', text);
}
myCaller();
Javascript 引擎扫描整个脚本以查看是否定义了任何变量或函数。在这个提升阶段,如果它找到 const
或 let
,它会为它们分配内存但不会使它们成为 Window 对象的一部分。因此,当您在全局上下文中引用 this
时,它指的是 window 对象,而 foo
不是 window 对象的 属性。这就是为什么,即使你把 const foo
放在 myCaller
定义之上,它也不起作用。
在 class 的情况下,如果您尝试直接调用 foo()
而不引用它,它会尝试从封闭的上下文中访问它,而您的示例中没有定义它。所以它会抛出错误。如果您在 class 之外用 var
定义另一个 foo()
或直接定义为 foo = (text) => ...
,它将起作用。
( this
可能并不总是指全局上下文。函数和 classes 可以有自己的自定义上下文,而 this
会引用该上下文。但是当函数或 classes 没有定义自定义上下文,全局上下文将是 this
关键字将引用的上下文。this
未定义函数和 class在严格模式下是默认的。有几个这样的警告需要考虑。)