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

IT技术 javascript function jslint jshint
2021-01-19 11:56:38

原问题:

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

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

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

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

4个回答

tl;dr如果你在一切都加载之前不打电话,你应该没问题。


编辑:有关还涵盖一些 ES6 声明 ( let, const)的概述https : //developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Scope_Cheatsheet

这种奇怪的行为取决于

  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;

var声明“抛出”的创作foo,以最顶端,但并不值分配给它。函数声明紧随其后,最后为 分配了一个值foo

而这个呢?

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

只有声明foo移动到顶部。分配仅在调用 to 之后出现bar,在所有提升发生之前。

最后,为了简洁:

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() {}

正如我们之前看到的,只有创建的foo被提升,赋值出现在它出现在“原始”(未提升)代码中的地方。当bar被调用时,它是在foo被赋值之前,所以foo === undefined.现在在 的函数体中bar,就好像您在执行undefined(),这会引发错误。

你如何确保一切都加载有什么共同的做法吗?
2021-03-27 11:56:38
很抱歉挖掘这个问题,但是像 Array.prototype.someMethod = function(){} 这样的重载被提升了吗?如果这些类型的东西在我的脚本末尾,我似乎会遇到错误。
2021-04-05 11:56:38

主要原因可能是 JSLint 只对文件执行一次传递,因此它不知道您定义这样的函数。

如果您使用了函数语句语法

function foo(){ ... }

实际上在声明函数的地方没有任何区别(它的行为总是像声明在开头一样)。

另一方面,如果您的函数设置为常规变量

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

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


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

对文件的开头发表评论

/*globals foo1 foo2 foo3*/

或者您可以在那里使用文本框。(我也认为你可以在参数中将它传递给内部 jslint 函数,如果你能插手的话。)

谢谢。那么 /* globals */ 行会起作用吗?好 - 任何让 JsHint 喜欢我的东西。我还是 JavaScript 的新手,刷新页面时会出现莫名其妙的停顿,但没有报告错误。所以我认为解决方案是遵守所有规则,然后看看它是否仍然发生。
2021-04-02 11:56:38

有太多人在推行关于 JavaScript 应该如何编写的任意规则。大多数规则是彻头彻尾的垃圾。

函数提升是 JavaScript 的一个特性,因为它是一个好主意。

当你有一个内部函数通常是内部函数的效用时,将它添加到外部函数的开头是一种可以接受的编写代码的风格,但它确实有一个缺点,你必须通读细节才能得到什么外部函数确实如此。

您应该在整个代码库中坚持一个原则,要么将私有函数放在module或函数中,要么放在最前面,要么放在最后。JSHint 有利于加强一致性,但您应该绝对调整 .jshintrc 以满足您的需要,而不是将您的源代码调整为其他人古怪的编码概念。

您可能会在野外看到的一种编码风格应该避免,因为它没有任何优势,只会给您带来重构的痛苦:

function bigProcess() {
    var step1,step2;
    step1();
    step2();

    step1 = function() {...};
    step2 = function() {...};
}

这正是函数提升要避免的。只需学习语言并发挥其优势即可。

仅提升函数声明而不提升函数表达式(赋值)。