在 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();
您在全局上下文中声明的任何变量(除了
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
是未定义的。有几个这样的警告需要考虑。)