关于编译和执行
编译和执行
历史上,计算机语言分为两组:静态语言(例如,Fortran 和 C,其中变量类型是在编译时静态指定的)和动态语言(例如,Smalltalk 和 JavaScript,其中变量的类型可以在运行时改变),主要区别是变量类型的确定。
静态语言通常编译成目标机器的本地机器代码(或汇编代码)程序,该程序在运行时直接由硬件执行。动态语言由解释器执行,不产生机器语言代码。
后来,虚拟机(VM)的概念开始流行,它其实只是一个高级的解释器,虚拟机使语言移植到新的硬件平台更容易。因此,VM 的输入语言常常是中间语言。例如,一种编程语言(如 Java )被编译成中间语言(字节码),然后在VM( JVM )中执行。
另外,现在有即时(JIT)编译器。JIT 编译器在程序执行期间运行,即时编译代码。而原先在程序创建期间,运行时之前执行的编译器称为 AOT 编译器。
一般来说,静态语言才适合 AOT 编译为本地机器代码,因为机器语言通常需要知道数据的类型,而动态语言中的类型事先并不确定。因此,动态语言通常被解释或 JIT 编译。
在开发过程中,AOT 编译开发周期长(从更改程序到能够执行程序以查看更改结果的时间),总是很慢。但是 AOT 编译产生的程序可以更可预测地执行,并且运行时不需要停下来分析和编译。AOT 编译的程序也更快地开始执行(因为它们已经被编译)。
与此相反的是,JIT 编译提供了更快的开发周期,但可能导致执行速度较慢或时快时慢。特别是,JIT 编译器启动较慢,因为当程序开始运行时,JIT 编译器必须在代码执行之前进行分析和编译。
以上就是背景知识。
Reference
箭头函数和类普通函数、constructor 里 bind 的函数有什么区别
class funcs { constructor() { this.fun_b = this.fun_b.bind(this); } fun_a() { console.log('a'); } fun_b() { console.log('b') } fun_c = () => { console.log('c') } }
babel 编译后:
// ... var funcs = /*#__PURE__*/ function () { function funcs() { _classCallCheck(this, funcs); _defineProperty(this, "fun_c", function () { console.log('c'); }); this.fun_b = this.fun_b.bind(this); } _createClass(funcs, [{ key: "fun_a", value: function fun_a() { console.log('a'); } }, { key: "fun_b", value: function fun_b() { console.log('b'); } }]); return funcs; }();
从编译结果可得出结论:
- 箭头函数,每一次实例化的时候,都会调用 defineProperty 将箭头函数内容绑定在当前实例上下文上;
- 类普通函数和在构造函数中绑定的函数,都会挂载到 prototype 上,但是要注意,在 constructor 中绑定的函数,在每次实例后将函数绑定到当前实例上下文上;
- 对比来看建议直接使用箭头函数,使用 bind 方式的话,不仅会多挂载一个 prototype 的函数,每一次实例化都会额外产生多一个函数。
class 内对于 = 号声明的方法、变量,都会将其作为实例的属性,而对于非 = 号声明的属性,则是放在原型链上,在继承方面需要多加留意。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论