JavaScript 函数顺序:为什么它很重要?

2022-08-30 05:09:30

原始问题:

当我的JavaScript调用一个函数时,JSHint会抱怨,该函数在页面下方定义,而不是调用它。但是,我的页面是针对游戏的,在下载整个内容之前不会调用任何函数。那么,为什么订单函数出现在我的代码中很重要呢?

编辑:我想我可能已经找到了答案。

http://www.adequatelygood.com/2010/2/JavaScript-Scoping-and-Hoisting

我在里面呻吟。看起来我需要再花一天时间重新排序六千行代码。JavaScript的学习曲线一点也不陡峭,但它非常愚蠢。


答案 1

tl;博士如果你在加载所有内容之前不调用任何内容,你应该没问题。


编辑:对于概述,其中还涵盖了一些ES6声明(,):https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Scope_Cheatsheetletconst

这种奇怪的行为取决于

  1. 如何定义函数和
  2. 当您打电话给他们时。

下面是一些示例。

bar(); //This won't throw an error
function bar() {}

foo(); //This will throw an error
var foo = function() {}
bar();
function bar() {
    foo(); //This will throw an error
}
var foo = function() {}
bar();
function bar() {
    foo(); //This _won't_ throw an error
}
function foo() {}
function bar() {
    foo(); //no error
}
var foo = function() {}
bar();

这是因为一种叫做吊装的东西!

定义函数的方法有两种:函数声明和函数表达式。这种差异是令人讨厌的和微小的,所以让我们说这个稍微错误的事情:如果你把它写成,它是一个声明,当你把它写成一个(或者一个分配给返回的匿名函数,类似的东西),它是一个函数表达式function name() {}var name = function() {}

首先,让我们看一下变量的处理方式:

var foo = 42;

//the interpreter turns it into this:
var foo;
foo = 42;

现在,如何处理函数声明

var foo = 42;
function bar() {}

//turns into
var foo; //Insanity! It's now at the top
function bar() {}
foo = 42;

这些语句将 创建的“抛出”到最顶部,但尚未为其赋值。函数声明紧随其后,最后将值分配给 。varfoofoo

那又如何呢?

bar();
var foo = 42;
function bar() {}
//=>
var foo;
function bar() {}
bar();
foo = 42;

只有 的声明被移到顶部。只有在调用 to 之后,即在所有吊装发生之前,才进行分配。foobar

最后,为了简洁起见:

bar();
function bar() {}
//turns to
function bar() {}
bar();

那么,函数表达式呢

var foo = function() {}
foo();
//=>
var foo;
foo = function() {}
foo();

就像常规变量一样,首先在作用域的最高点声明,然后为其分配一个值。foo

让我们看看为什么第二个示例会引发错误。

bar();
function bar() {
    foo();
}
var foo = function() {}
//=>
var foo;
function bar() {
    foo();
}
bar();
foo = function() {}

正如我们之前所看到的,只有 创建是吊装的,任务来自“原始”(未吊装)代码中出现的位置。当 调用 时,它是在被赋值之前,所以 .现在在 的函数体中,就好像你正在做一样,这会引发一个错误。foobarfoofoo === undefinedbarundefined()


答案 2

主要原因可能是JSLint只对文件进行一次传递,所以它不知道你会定义这样一个函数。

如果使用了函数语句语法

function foo(){ ... }

实际上,声明函数的位置根本没有区别(它的行为总是像声明在开头一样)。

另一方面,如果你的函数被设置为像常规变量一样

var foo = function() { ... };

你必须保证在初始化之前不会调用它(这实际上可能是错误的来源)。


由于对大量代码进行重新排序很复杂,并且本身可能是错误的来源,因此我建议您搜索解决方法。我很确定你可以事先告诉JSLint全局变量的名称,这样它就不会抱怨未声明的东西。

在文件开头添加注释

/*globals foo1 foo2 foo3*/

或者你可以在那里使用一个文本框。(我还认为,如果您可以插手,则可以在参数中将其传递给内部jslint函数。