今天有人问我,我无法给出适当的答案。
Typescript转换为JS。然后是摇晃的树,“较少”(可选)以及进行部署的过程。但是,那样的东西(afaik)与“编译”没有任何关系。一切都捆绑在一起并进行了严格的优化,但是实际上并没有被编译,对吗?
甚至还有一个“提前”编译器,它确实可以做得很出色。我想念什么?
JavaScript本身仍在解释,对吗?
今天有人问我,我无法给出适当的答案。
Typescript转换为JS。然后是摇晃的树,“较少”(可选)以及进行部署的过程。但是,那样的东西(afaik)与“编译”没有任何关系。一切都捆绑在一起并进行了严格的优化,但是实际上并没有被编译,对吗?
甚至还有一个“提前”编译器,它确实可以做得很出色。我想念什么?
JavaScript本身仍在解释,对吗?
Answers:
您假定编译意味着获取源代码并生成机器代码,低级代码等。但是编译实际上只是意味着获取一个源代码并将其转换为另一个。因此,可以合理地说采用Typescript并生成JavaScript是一种编译形式。它与c#编译为IL语言时的行为(例如)没有什么不同。
就是说,我会说一个更好的词是Transpiling。我建议将Typescript编译器更好地描述为Transpiler。
区别是微妙的,可以将编译器视为编译器的一种。但是(纯)编译语言(通常)是将高级语言转换为低级(较近的机器代码)语言,例如C#示例。编译器将高级语言转换为相似级别(抽象)的语言(也是高级)。*
编译后的代码的结果通常不是您自己编写的语言。转译器的结果是另一种高级语言。从理论上讲,您可以编写IL(作为示例),但实际上它是由编译器生成的,并且没有工具或支持这样做的工具,您只能通过编译C#/ vb.net来生成IL。Javascript本身就是一种可用(和使用)的编程语言。
*很多警告,因为这些词的定义及其用法非常含糊
您似乎一口气问了三个问题:
编译器和翻译器有什么区别?
@JörgWMittag对这个问题提供了很好的答案。
Angular和TypeScript是否实现编译器或编译器?
TS和Angular都实现了真正的编译器。它们遵循与产生汇编代码的C / C ++编译器相同的词法分析,语法分析,语义分析和代码生成阶段(可能出于优化目的)。您可以看到Angular和TS中的类/文件夹都被命名为“ compiler” 。
角度编译器与TypeScript编译器并没有真正的关系。这些是完全不同的编译器。
是否有单独的Angular编译器?它编译什么?
Angular有两个编译器:
视图编译器的工作是将您为组件模板指定的模板转换为组件的内部表示,该内部表示是视图工厂,然后用于实例化视图实例。
除了将所述模板,视图编译器还编译在像装饰形式的各种元数据信息@HostBinding
,@ViewChild
等等。
假设您这样定义一个组件及其模板:
@Component({
selector: 'a-comp',
template: '<span>A Component</span>'
})
class AComponent {}
编译器使用这些数据生成以下稍微简化的组件工厂:
function View_AComponent {
return jit_viewDef1(0,[
elementDef2(0,null,null,1,'span',...),
jit_textDef3(null,['My name is ',...])
]
它描述了组件视图的结构,并在实例化组件时使用。第一个节点是元素定义,第二个节点是文本定义。您可以看到每个节点在通过参数列表实例化时都获得了所需的信息。解析所有必需的依赖项并在运行时提供它们是编译器的工作。
我强烈建议您阅读以下文章:
另外,请参见“ Angular AOT和JIT编译器之间的区别是什么”的答案。
模块编译器的工作是创建一个模块工厂,该工厂基本上包含提供者的合并定义。
有关更多信息,请阅读:
打字稿转成JS。然后是摇晃的树,“较少”(可选)以及进行部署的过程。但是,那样的东西(afaik)与“编译”没有任何关系。一切都捆绑在一起并进行了严格的优化,但是实际上并没有被编译,对吗?
编译是指将用语言A编写的程序转换为用语言B编写的语义上等效的程序,以便根据语言B的规则评估编译后的程序(例如,用B的解释程序对其进行解释)会产生相同的结果,并具有与根据语言A的规则评估原始程序具有相同的副作用(例如,使用A的解释器对其进行解释)。
汇编仅仅意味着一个程序翻译从语言甲语言乙。这就是全部。(还要注意,A和B完全可能是同一语言。)
在某些情况下,对于某些类型的编译器,我们有更专门的名称,具体取决于A和B以及编译器的作用:
另外,请注意,较早的来源可能使用术语“翻译”和“翻译”,而不是“编译”和“编译器”。例如,C谈论“翻译单位”。
您也可能会偶然发现术语“语言处理器”。根据定义,这可能意味着编译器,解释器,或者意味着编译器和解释器。
JavaScript本身仍在解释,对吗?
JavaScript是一种语言。语言是一组逻辑规则和限制。语言不会被解释或编译。语言只是有。
编译和解释是编译器或解释器的特征(duh!)。每种语言都可以用编译器实现,每种语言都可以用解释器实现。许多语言同时具有编译器和解释器。许多现代的高性能执行引擎都具有至少一个编译器和至少一个解释器。
这两个术语属于不同的抽象层。如果英语是一种打字语言,则“解释语言”将是一种类型错误。
还要注意,某些语言既没有解释器也没有编译器。有些语言根本没有实现。它们仍然是语言,您可以用它们编写程序。您只是无法运行它们。
另外,请注意,所有内容都在某个时刻被解释:如果您想执行某件事,则必须对其进行解释。编译只是将代码从一种语言翻译成另一种语言。它不会运行。解释运行它。(有时,当解释器以硬件实现时,我们称其为“ CPU”,但它仍然是解释器。)
恰当的例子:当前存在的每个主流JavaScript实现都有一个编译器。
V8最初是一个纯粹的编译器:它直接将JavaScript编译为适当优化的本机代码。后来,添加了第二个编译器。现在,有两种编译器:轻量级编译器,可生成经过适当优化的代码,但编译器本身非常快,并且使用的RAM很少。该编译器还将配置文件代码注入已编译的代码中。第二个编译器是重量更重,运行更慢,更昂贵的编译器,但是生成的代码更紧密,更快。它还使用第一个编译器注入的性能分析代码的结果来做出动态优化决策。同样,基于该概要分析信息来决定使用第二个编译器重新编译哪些代码。请注意,任何时候都不会涉及口译员。V8从不解释,而是始终进行编译。它没有 甚至还包含口译员。(实际上,我相信现在确实如此,我正在描述前两个迭代。)
SpiderMonkey将JavaScript编译为SpiderMonkey字节码,然后对其进行解释。解释器还会分析代码,然后将最常执行的代码由编译器编译为本机代码。因此,SpiderMonkey包含两个编译器:一个从JavaScript到SpiderMonkey字节码,另一个从SpiderMonkey字节码到本机代码。
几乎所有的JavaScript执行引擎(V8除外)都遵循这种AOT编译器模型,该模型将JavaScript编译为字节码,并且使用混合模式引擎在解释和编译该字节码之间切换。
您在评论中写道:
我真的以为涉及机器代码。
“机器代码”甚至是什么意思?
一个人的机器语言是另一人的中间语言,反之亦然?例如,有些CPU可以本地执行JVM字节码,在这种CPU上,JVM字节码是本地机器代码。并且有x86机器代码的解释器,当您运行这些x86机器代码时,将解释为字节码。
有一个用Java编写的名为JPC的x86解释器。如果我在本机JVM CPU上运行的JPC上运行x86机器代码…这是字节码,哪个是本机代码?如果我将x86机器代码编译为JavaScript(是的,有工具可以做到)并在手机的浏览器(具有ARM CPU)中运行它,这是字节码又是本机代码?如果我正在编译的程序是SPARC仿真器,并且使用它来运行SPARC代码怎么办?
请注意,每种语言都会产生一台抽象机器,并且是该机器的机器语言。因此,每种语言(包括高级语言)都是本机代码。另外,您可以为每种语言编写翻译。因此,每种语言(包括x86机器代码)都不是母语。
使您编写的代码在浏览器上运行涉及两件事:
1)将Typescript转换为JavaScript。这是一个已解决的问题。我认为他们只是使用webpack。
2)将角度抽象编译到JavaScript中。我的意思是诸如组件,管道,指令,模板等之类的东西。
如果您真的对第二个角度(角编译器)感兴趣,请观看编译器作者Tobias Bosch在AngularConnect 2016上解释Angular编译器。
我认为在转译和编译之间存在一些混乱。这无关紧要,只是个人喜好,它们都只是代码表示之间的转换。但是我个人使用的定义是,在两种不同语言之间以类似的抽象级别(例如,打字稿转换为javascript)进行转译,而编译则需要将抽象级别降低。我认为从模板,组件,管道,指令等到javascript都是在抽象阶梯上走下坡路的原因,这就是为什么将其称为编译器。
从Angular 4到5的最重要的变化之一是编译器的编写速度更快,更彻底。过去,Angular应用程序使用了我们所谓的即时(JIT)编译,即在运行时在浏览器中运行该应用程序之前对其进行编译。Angular 5中的编译器更新促进了向AOT的迁移,这使应用程序运行得更快,因为它在运行应用程序时执行较少的编译。从Angular CLI的1.5版本开始,在任何生产版本中默认都会启用AOT。
假设我们要构建一个用于部署的应用程序并运行以下命令:
ng build --prod
发生了一些事情:生产版本,缩小,捆绑资产,文件名哈希,摇树,AOT ...(我们可以使用标志启用/禁用此功能,例如aot = false)。简而言之,prod标志通过使用ngc(Angular编译器)进行AOT编译来创建应用程序的优化包,以创建适合浏览器的优化代码(是的,它会预编译模板)。
TypeScript编译器tsc负责编译TypeScript文件。它是负责实现TypeScript功能(例如静态类型)的编译器,结果是纯JavaScript,其中删除了TypeScript关键字和表达式。
TypeScript编译器具有两个主要功能:它是一个编译器和一个类型检查器。编译器将TypeScript转换为JavaScript。它会对您的源代码进行以下转换:
调用它,编译器将搜索tsconfig.json中加载的配置(可在此处找到所有编译器选项的详细列表以及默认值)。
在大多数方面,TypeScript编译器的工作原理与任何编译器一样。但是有一个区别可以解决这个问题:默认情况下,即使遇到错误,编译器仍会继续发出JavaScript代码。幸运的是,可以通过noEmitOnError
在tsconfig.json文件中将配置设置设置为true来禁用此行为。
需要注意的是:tsc和ngc具有不同的用途,而不是一个选择另一个。这个答案可能很有趣。
这个答案是根据以下书籍的内容而精心设计的
Cloe,M.(2018年)。“ Angular 5项目:学习使用70多个项目构建单页Web应用程序”。
杜威,B。格罗斯尼克劳斯,K。贾比克瑟(2017)。“使用Visual Studio 2017构建Web应用程序:使用.NET Core和现代JavaScript框架”。
Freeman,A.(2019年)。“基本TypeScript:从初学者到专业人士”。
Ghiya,P.(2018年)。“ TypeScript微服务”。
Iskandar,A.,Chivukulu,S.(2019年)。“使用Angular和Bootstrap进行Web开发-第三版”。
Hennessy,K.,Arora,C.(2018年)。“示例角度6”。
Jansen,R.,Wolf,I.,Vane,V.(2016年)。“ TypeScript:现代JavaScript开发”。
Mohammed,Z.(2019年)。“角度项目”。
Seshadri,S.(2018年)。“角度:启动并运行”。
Wilken,J.(2018年)。“行动中的角度”。