难道一个真正的浏览器通过读取一行一行的JavaScript或者它进行多次传递? [英] Does a browser truly read JavaScript line by line OR does it make multiple passes?

查看:118
本文介绍了难道一个真正的浏览器通过读取一行一行的JavaScript或者它进行多次传递?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

据我了解,JavaScript是间preTED而不是编译。这里没有问题。不过,我一直在这里读了JavaScript执行对飞,这行读取一次。这个想法是混淆了我不少,当涉及到下面的例子:

I understand that JavaScript is interpreted and not compiled. No problem there. However, I keep reading here that JavaScript is executed "on the fly" and that lines are read one at a time. This idea is confusing me quite a bit when it comes to the following example:

writeToConsole();

function writeToConsole() {
    console.log("This line was reached.");
}

有关记录,code的此位将写入控制台就好了。不过,浏览器怎么会知道存在的 exampleFunction()如果尚未达到功能?

For the record, this bit of code will write to the console just fine. Still, how would the browser know of the existence of exampleFunction() if it had not yet reached the function?

在换句话说,的恰恰是这个函数第一间preTED?

In other words, when exactly is this function first interpreted?

推荐答案

首先,你作出不正确的假设:现代JavaScript的编译。发动机就像 V8 ,的 SpiderMonkey的和硝基编译JS源到本地机code 主机平台。

First, you make an incorrect assumption: modern JavaScript is compiled. Engines like V8, SpiderMonkey, and Nitro compile JS source into the native machine code of the host platform.

即使在较旧的引擎,JavaScript是不是的间preTED 的。他们变换的源$ C ​​$ C到字节code ,该发动机的virtual机执行。

Even in older engines, JavaScript isn't interpreted. They transform source code into bytecode, which the engine's virtual machine executes.

这其实是东西,Java和.NET语言是如何工作的:当你编译你的应用程序,你实际上是转换源$ C ​​$ C到平台的字节code,的Java字节code CIL 分别。然后,在运行时, JIT编译器编译字节code成机器code

This is actually how things in Java and .NET languages work: When you "compile" your application, you're actually transforming source code into the platform's bytecode, Java bytecode and CIL respectively. Then at runtime, a JIT compiler compiles the bytecode into machine code.

只有很旧,简单的JS引擎实际上间preT JavaScript源$ C ​​$ C,因为除pretation是很慢的。

Only very old and simplistic JS engines actually interpret the JavaScript source code, because interpretation is very slow.

那么,如何JS的编写工作?在第一阶段中,源文本被转换成一个抽象语法树(AST)时,一个数据结构,再presents您code。在机器可以处理的格式。从概念上讲,这很像HTML文本如何转化成其 DOM 重新presentation,这是你的code实际工作用。

So how does JS compilation work? In the first phase, the source text is transformed into an abstract syntax tree (AST), a data structure that represents your code in a format that machines can deal with. Conceptually, this is much like how HTML text is transformed into its DOM representation, which is what your code actually works with.

为了生成AST,发动机必须处理原始字节的输入。这通常是通过一个词法分析器的完成。词法分析器并没有真正读取文件行由行;而是读逐字节,使用语言的语法规则的源文本转换成的标记的。词法分析器然后通过令牌到解析器,这是实际构建AST流。解析器验证令牌形成一个有效的序列。

In order to generate an AST, the engine must deal with an input of raw bytes. This is typically done by a lexical analyzer. The lexer does not really read the file "line-by-line"; rather it reads byte-by-byte, using the rules of the language's syntax to convert the source text into tokens. The lexer then passes the stream of tokens to a parser, which is what actually builds the AST. The parser verifies that the tokens form a valid sequence.

您现在应该能够看到明明白白为什么一个语法错误$ P $从所有工作pvents您code。如果意外字符出现在你的源文本,发动机不能产生一个完整的AST,它不能移动到下一个阶段。

You should now be able to see plainly why a syntax error prevents your code from working at all. If unexpected characters appear in your source text, the engine cannot generate a complete AST, and it cannot move on to the next phase.

一旦引擎有一个AST:

Once an engine has an AST:


  • 一个跨preTER可能只是开始直接从AST执行指令。这是很慢的。

  • 系统JS VM实现使用AST生成字节code,然后开始执行字节code。

  • 编译器使用AST来生成机器code ,该CPU执行

  • An interpreter might simply begin executing the instructions directly from the AST. This is very slow.
  • A JS VM implementation uses the AST to generate bytecode, then begins executing the bytecode.
  • A compiler uses the AST to generate machine code, which the CPU executes.

所以,你现在应该能看到的最小的,JS执行发生在两个阶段。

So you should now be able to see that at minimum, JS execution happens in two phases.

然而,执行的阶段确实有,为什么你的例子可以没有任何影响。它的工作原理是因为规则定义程序如何JavaScript中进行评估并执行的。这些规则可以很容易地被写入的方式,这样你的例子是行不通的,并就如何在发动机本身实际上间preTS /编译源$ C ​​$ C无影响。

However, the phases of execution really have no impact on why your example works. It works because of the rules that define how JavaScript programs are to be evaluated and executed. The rules could just as easily be written in a way such that your example would not work, with no impact on how the engine itself actually interprets/compiles source code.

具体而言,JavaScript有 俗称为特征的提升的。为了了解冲顶,你必须明白之间的差异的函数声明的和的功能前pression

Specifically, JavaScript has a feature commonly known as hoisting. In order to understand hoisting, you must understand the difference between a function declaration and a function expression.

简单地说,一个函数声明是当你声明一个新的功能,将在其他地方称为:

Simply, a function declaration is when you declare a new function that will be called elsewhere:

function foo() {

}

一个函数前pression是,当你使用函数关键字在期望一个的前pression 的,这样任何地方为变量赋值或参数:

A function expression is when you use the function keyword in any place that expects an expression, such as variable assignment or in an argument:

var foo = function() { };

$.get('/something', function() { /* callback */ });

JavaScript的任务是发挥作用的声明的(第一类)分配给变量名的在执行上下文的地方开始不管该声明出现在源文本(的情况下)。一个的执行上下文的大致equatable到的范围的&ndash的;在平原而言,code函数里面,或者你的脚本的顶部如果没有一个函数中。

JavaScript mandates that function declarations (the first type) be assigned to variable names at the beginning of an execution context, regardless of where the declaration appears in source text (of the context). An execution context is roughly equatable to scope – in plain terms, the code inside a function, or the very top of your script if not inside a function.

这可能导致非常奇怪的行为:

This can lead to very curious behavior:

var foo = function() { console.log('bar'); };

function foo() { console.log('baz'); }

foo();

你所期望记录到控制台?如果你只是读code线,你可能会认为巴兹。但是,它实际上将登陆,因为上面的前pression来分配悬挂声明到

What would you expect to be logged to the console? If you simply read the code linearly, you might think baz. However, it will actually log bar, because the declaration of foo is hoisted above the expression that assigns to foo.

于是得出结论:


  • JS​​源$ C ​​$ C是从来没有读行由行。

  • JS​​源$ C ​​$ C实际上是编译(在这个词的真正意义上)在现代浏览器。

  • 发动机编译code在多遍。

  • 的行为是你的榜样是JavaScript语言,它不是如何编译或跨preTED规则的副产品。

这篇关于难道一个真正的浏览器通过读取一行一行的JavaScript或者它进行多次传递?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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