Dart vs JavaScript - 它们是编译型语言还是解释型语言?

8
Dart被认为是一种编译语言还是解释语言?同样的问题也适用于JavaScript。
问题的原因:
我一直在观看一次采访,采访中提到了dart的创始人,在7:10时Lars Bak说:
"When you [...] in a JavaScript program, you actually execute JavaScript before you start running the real program. In Dart, you don't execute anything before the first instruction in main is being executed".
听起来他似乎在说JavaScript是一种编译语言,而Dart是一种解释语言。这是真的吗?
Dart VM不是一个编译器吗?
3个回答

14

取决于“解释”和“编译”语言的定义。即使如此,它始终取决于实现。

Lars 的意思是 JavaScript 通过执行代码来建立其类结构(和其他全局状态)。在 Dart 中,全局状态由语言语法描述,因此只需要解析(甚至大部分可以先跳过)。因此,Dart 程序可以比 JavaScript 程序更快地开始执行“真正”的代码。

显然,这仅适用于 Dart VM,因为已编译为 JavaScript 的程序必须使用 JavaScript 机制来构建它们的类。

编辑(更多细节):

例如,以下极其简单的类 A

在 Dart 中:

class A {
  final x;
  A(this.x);
  foo(y) => y + x;
}

在JavaScript中:

function A(x) { this.x = x; }
A.prototype.foo = function(y) { return y + this.x; }
当Dart VM启动时,它会通过程序开始启动。 它看到了`class`关键字,读取了类名(`A`),然后可以通过计算开放和关闭括号的数量并确保它们不在字符串中来简单地跳到类的末尾。 在`A`被实例化之前,它不关心`A`的内容。现实情况是,它实际上会查看类并找到所有成员,但直到需要它们的方法时,才会阅读这些方法的内容。无论如何:它会在一个非常快速的处理步骤中执行此操作。
在JavaScript中,事情变得更加复杂:一个快速的VM可以跳过函数`A`的实际体(类似于Dart的做法),但是当它看到`A.prototype.foo = ...`时,它需要执行代码以创建原型对象。也就是说,它需要分配一个函数对象(`A`),查找其原型属性,使用新函数对象更改此对象(添加一个新属性)。换句话说,为了甚至看到你有一个类,你需要执行代码。

谢谢@Florian Loitsch,但是你能否解释一下你所说的“在Dart中,全局状态由语言语法描述,因此只需要解析”是什么意思?难道不是每种语言都需要解析吗?如果您能再解释一遍,我会非常感激。 - Cheshie
1
因此, Dart 程序比 JavaScript 程序更快地开始执行“真正”的代码。在浏览器中这并不完全正确,因为 main() 在 DOM 加载完成之后才被调用。JavaScript 可以在 DOM 准备就绪之前执行,因此在实际应用中,JavaScript 可能会更早地执行。来源。但从语言角度来看,你是正确的。 - beatgammit

6
作为一种编程语言,Dart的主要实现形式可以被呈现为虚拟机(VM),它是使用该语言编写程序的运行时。
当前的虚拟机实现为“即时”(JIT)运行环境引擎。
这意味着程序不是解释执行而是编译执行。但是这个编译过程(将源代码翻译成机器指令)会在未知的时间段内被延迟执行。
这使得虚拟机可以无限期地推迟执行某些操作或永远不执行它们。
假设您有一个非常庞大而复杂的程序,其中有很多类可能在当前短生命周期会话中从未被使用。
JIT编译允许不编译所有未使用的类,而只需将其解析为特殊的标记。稍后这些标记将用于(按需)将它们翻译成中间语言以构建机器代码。
此过程对程序用户来说是透明的。只有为程序正确工作所需的源代码才会被编译成机器代码。
有些源代码可能永远不会被编译,这节省了大量时间。
结论:
如果Dart语言在其初始状态下作为虚拟机使用,则会编译成机器代码。

抱歉,@mezoni,我没有完全理解您的意思:您是说Dart是使用JIT编译的吗?谢谢。 - Cheshie
Dart源代码可以被强制转换为“tokens”文件。这个过程被称为创建“snapshot”文件。快照不是字节码文件,而只是解析的标记。这个快照可以在VM中执行。内部VM使用JIT技术执行源代码或快照。 - mezoni
虽然这个问题是7年前的,但自从我开始学习Flutter和Dart以来,我必须问一下我的疑惑。假设我有3个类A、B、C,而我只实例化了A。这是否意味着类B和C是死代码,被标记化但从未被使用,或者它们根本没有被标记化? - Yashasvi Bhatt
1
@YashasviBhatt 不是“死代码”,而是未使用的代码。当然,所有代码都被标记化,甚至预编译成中间语言(不是机器相关的语言)。 - mezoni

-1
Dart编译成JavaScript,而JavaScript是一种解释性语言。通常,“编译”语言指的是编译成特定平台机器代码的语言,直接在CPU上运行且不需要解释器来运行,但这对于JS和Dart都不适用。因此,我认为JS和Dart都是解释性语言。

谢谢Wraychus,但首先:据我所知,Dart可以由Dart VM解释/编译,也可以转换为JS。那么我的问题是:使用Dart VM时,它是编译还是解释?其次,如果两种语言都是解释的,那么Lars Bak引用的那句话对我来说就没有意义了。有其他的解释吗? - Cheshie
Dart VM 执行 Dart 源代码,无需先将 Dart 代码编译为字节码(与 Java 不同)。 - Pixel Elephant
所以这是很久以前的事了。目前至少存在四种技术。1. 解释型(原始语言)。2. 编译成二进制文件。3. 转换为字节码+在VM中执行+在执行之前编译。4. 作为脚本分发+在VM中执行+在执行之前编译。Javascript和Dart是第四种。 - mezoni

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接