为什么JavaScript不需要main()函数? [英] Why doesn't JavaScript need a main() function?

查看:62
本文介绍了为什么JavaScript不需要main()函数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

许多编程语言都需要一个特殊的用户编写函数来标记开始执行.例如,在C语言中,此函数必须始终具有名称 main().在但是,JavaScript不是必需的.

Many programming languages require a special user-written function that marks the begin of the execution. For example, in C this function must always have the name main(). In JavaScript, however, such a function is not required.

在JavaScript中缺少如此专用的顶级功能的逻辑原因是什么?我知道这是某种理论上的问题,但是我无法在线找到答案.

What are the logical reason for the absence of such a dedicated top level function in JavaScript? I know this is some kind of theoretical question, but I cannot find an answer online.

推荐答案

因为整个代码块实际上是一个很大的 main .在JavaScript中,就像函数一样,全局代码可以具有函数代码可以具有的所有构造,并且可以逐步执行.实际上,当JS引擎整体上处理代码块时,它执行的功能与处理函数调用时几乎相同.请参见规范的 10.4.1 (输入全局代码")和

Because the entire code block is effectively one big main. In JavaScript, global code can have all of the constructs function code can have, and has stepwise execution, just like functions do. In fact, when the JS engine processes the code block as a whole, it does very nearly the same things that it does when processing a function call. See the specification's sections 10.4.1 ("Entering Global Code") and 10.4.3 ("Entering Function Code") and note how similar they are.

C不允许在全局级别使用逐步代码(您可以使用各种初始化程序,并且它们可以进行某种逐步操作,但这是不同的主题).因此,C需要一个显式的入口点( main ).在JavaScript中,入口点是代码的开头.

C doesn't allow stepwise code at the global level (you can have all sorts of initializers, and they can get kind of stepwise, but that's a different topic). And so C needs an explicit entry point (main). In JavaScript, the entry point is the beginning of the code.

关于下面有关全局代码是否顺序的问题.答案是肯定的,就像函数中的代码一样.所以:

Regarding your question below about whether global code is sequential. The answer is yes, it's exactly like code in a function that way. So:

var x, y, z;
x = 1;
y = 2;
z = x + y;
alert("z is " + z);

...将提醒"z为3" .该代码按从上到下的顺序运行.

...will alert "z is 3". The code runs sequentially, top to bottom.

在逐步执行代码之前,发生了几件事情,这很有用.最重要的是,在逐步代码开始之前,要处理输入范围的源文本中的所有声明.JavaScript有两种主要的声明类型:变量声明和函数声明:

There are a couple of things that happen before the stepwise code is executed, though, which is useful to know. The most significant is that any declarations in the source text of the scope being entered are processed before the stepwise code begins. JavaScript has two main types of declarations: Variable declarations, and function declarations:

  1. 在执行任何逐步代码之前,将使用 var 声明的任何变量的名称添加到作用域(值为 undefined ).(更多: 可怜,被误解的 var )

  1. The name of any variable declared with var is added to the scope (with the value undefined) before any stepwise code is executed. (More: Poor, misunderstood var)

函数声明,并将函数名称添加到作用域.(JavaScript还具有其他名称,称为函数 expression ,它是逐步执行的代码.有关更多信息,请参见下文.)

Function declarations are processed and the function names added to the scope before any stepwise code is executed. (JavaScript also has something else, called a function expression, which is stepwise code. More on that below.)

例如,在此源文本中:

var x;
x = 1;
foo();

function foo() {
}

声明是

var x;
function foo() {
}

逐步代码是

x = 1;
foo();

首先处理声明.这就是为什么对 foo 的调用起作用的原因.(这些相同的规则也适用于函数中的源文本.)这种在声明之前的处理有时称为吊装",因为从某种意义上说,声明是从其在源文本中的位置抬起并移到最开始的位置.我更喜欢将其视为源中的两次遍历:第一遍进行声明,第二遍执行逐步的代码.

The declarations are processed first. This is why the call to foo works. (These same rules apply to the source text within functions.) This processing of declarations before anything else is sometimes called "hoisting," because the declarations are in a sense lifted from their location in the source text and moved to the very beginning. I prefer to think of it as two passes through the source: The first pass does declarations, the second executes stepwise code.

(附带说明:在同一范围内多次声明一个变量是完全合法的(尽管毫无意义).同时声明两个具有相同名称的函数也是合法的;后一个声明将覆盖前一个声明.)

(Side note: Declaring a variable more than once in the same scope is perfectly legal [though pointless]. Declaring two functions with the same name is also legal; the latter declaration overrides the earlier one.)

(注释2:ES2015 [ES6]引入了 let const 变量声明,它们的行为与 var 有所不同.不能与它们一起声明两次变量,它们具有块作用域,并且您不能在声明该变量的语句之前使用该变量,因此它们大多不被吊起[有些东西轻微像吊起因为它们甚至可以防止在 let x 或任何行]之前访问包含范围内的阴影变量.)

(Side note 2: ES2015 [ES6] introduced let and const variable declarations, which behave somewhat differently from var. You can't declare a variable twice with them, they have block scope, and you can't use the variable prior to the statement where it's declared. So they're mostly not hoisted [there is something slightly like hoisting in that they prevent access to a shadowed variable in a containing scope even before the let x or whatever line].)

更多细节,可能还会有一些技术性:

More detail, and possibly getting a bit technical:

如果 var 在运行逐步代码之前发生,您可能会对此感到疑惑:

If var happens before the stepwise code is run, you may be wondering about this:

var x = 1;

这是在逐步代码之前还是作为代码的一部分发生?答案是,实际上,这只是两个非常不同的事物的简写:

Does that happen before stepwise code, or as part of it? The answer is that in reality, that's just shorthand for two very different things:

var x;
x = 1;

var x; 部分发生在逐步代码之前, x = 1; 部分是逐步代码,在我们按顺序到达时执行.所以:

The var x; part happens before the stepwise code, the x = 1; part is stepwise code and is executed when we reach it in the sequence. So:

alert(x); // "undefined" -- there **is** a variable `x`; it has the value `undefined`
var x = 1;
alert(x); // "1" -- now `x` has the value `1`

函数声明

JavaScript有两个不同但外观非常相似的东西:函数声明和函数表达式.通过是否将结果函数用作定义它的表达式的一部分,可以知道是哪一个.

Function declarations

JavaScript has two different, but very similar-looking, things: Function declarations, and function expressions. You can tell which is which by whether you're using the resulting function as part of the expression in which it's defined.

这是一个函数声明:

function foo() {
}

这些都是函数 expressions (我们将结果函数值用作表达式的一部分;在计算机科学术语中,该函数用作右手值):

These are all function expressions (we use the resulting function value as part of the expression; in computer science terminology, the function is used as a right-hand value):

// 1: Assigning the result to something
var x = function() {
};

// 2: Passing the result into a function
bar(function() {
});

// 3: Calling the function immediately
(function(){
})();

// 4: Also calling the function immediately (parens at end are different)
(function(){
}());

// 5: Also calling the function immediately
!function(){
}();

// 6: Syntax error, the parser needs *something* (parens, an operator like ! or
// + or -, whatever) to know that the `function` keyword is starting an *expression*,
// because otherwise it starts a *declaration* and the parens at the end don't make
// any sense (and function declarations are required to have names).
function(){
}();

规则是在逐步代码开始之前处理函数声明.与所有其他表达式一样,函数表达式也会在遇到它们的地方进行处理.

The rule is that function declarations are processed before the stepwise code begins. Function expressions, like all other expressions, are processed where they're encountered.

最后一点说明:这是一个 命名函数表达式:

One final side note: This is a named function expression:

var f = function foo() {
};

我们将其用作右侧值,因此我们知道它是一个表达式;但它的名称像函数声明一样.这是完全合法且合法的JavaScript,它的用途是创建一个具有适当名称( foo )的函数,作为逐步代码的一部分.函数的名称未 添加到范围中(就像它是一个函数声明一样).

We use it as a right-hand value, so we know it's an expression; but it has a name like function declarations do. This is perfectly valid and legal JavaScript, and what it's meant to do is create a function with a proper name (foo) as part of the stepwise code. The name of the function is not added to the scope (as it would be if it were a function declaration).

但是,您不会在很多地方看到命名函数表达式,因为JScript(Microsoft的JavaScript引擎)将它们命名为

However, you won't see named function expressions in very many places, because JScript (Microsoft's JavaScript engine) gets them horribly and utterly wrong, creating two separate functions at two different times.

这篇关于为什么JavaScript不需要main()函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆