为什么箭头函数必须声明在调用函数之上

问题描述 投票:0回答:1

在 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
指的是全局/文档级别

// 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 类中声明箭头函数时,它只能与

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();

javascript this arrow-functions
1个回答
2
投票

您在全局上下文中声明的任何变量(除了

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
都作为属性附加到窗口对象。现在您可以直接引用它们,例如
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
定义之上,它也不起作用。

在类的情况下,如果您尝试直接调用

foo()
而不引用它,它会尝试从封闭的上下文中访问它,而您的示例中未定义它。所以它会抛出错误。如果您在类外使用
foo()
定义另一个
var
或直接定义为
foo = (text) => ...
,它将起作用。

this
可能并不总是指全局上下文。函数和类可以有自己的自定义上下文,并且
this
将指代该上下文。但是当函数或类没有定义自定义上下文时,全局上下文context 将是
this
关键字所引用的上下文。默认情况下,在严格模式下,函数和类的
this
是未定义的。有几个这样的警告需要考虑。)

© www.soinside.com 2019 - 2024. All rights reserved.