javascript写字技巧_How JavaScript Work 学习笔记(一)

JavaScript 引擎

Chrome 的 V8 引擎包括两个主要组件:

动态内存管理 —— 用于分配内存

调用栈 —— 执行 JavaScript 代码的堆栈结构

JavaScript 引擎结构

运行时

除了 JavaScript 引擎用于执行代码和保存变量外,还有浏览器环境提供的 Web API。Web API 中包含 DOM、AJAX、setTimeout 等方法。

调用栈

JavaScript 是一个单线程的编程语言,所以它只有一个调用栈,即一次只能做一件事情。

只有一个调用栈的特性会带来两个问题:

调用栈太多会抛出堆栈溢出错误。

function foo() {

foo();

}

foo();

maximum call stack size exceeded

调用栈中执行某个行为时间太久会假死,浏览器抛出不可控制的错误 —— 浏览器没有响应。

浏览器未响应

V8 引擎中的两个编译器

在 V8 5.9 版本之前的浏览器引擎中有两个编译器:

full-codegen-一个简单且快速的编译器用来产出简单且运行相对缓慢的机器码。用于将 JavaScript 代码编译为机器码。

Crankshaft-一个更复杂(即时)优化的编译器用来产生高效的代码。它用于收集数据并优化 JavaScript 中可以优化的部分。

而在 V8.5.9 版本之后的浏览器引擎不再使用上述两个编译器了。新的 V8 解释器 Ignition 和 V8 最新的优化编译器 TurboFan 让引擎的性能提升了不少。

在 V8 引擎中书写最优代码的 5 条小技巧

对象属性的顺序:总是以相同的顺序实例化对象属性,这样隐藏类及之后的优化代码都可以被共享。

当我们使用 this.x = 100 的写法为对象添加属性时,会创建一个带有属性 x 的隐藏类。以此类推,再次添加 this.y = 200 那么会基于带有 x 属性的隐藏类再创建带有 x 和 y 属性的隐藏类。如果多个对象属性的添加顺序是一样的,那么就可以共享隐藏类了。反之,两个不同顺序实例化的对象所创建的隐藏类是不同的。

动态属性:实例化之后为对象添加属性会致使为之前隐藏类优化的方法变慢。应该在对象构造函数中赋值对象的所有属性。

方法:重复执行相同方法的代码会比每次运行不同的方法的代码更快(多亏了内联缓存)。

内联缓存会将重复执行的方法地址缓存下来,再次执行是绕开查找方法行为直接到方法地址去执行方法。

数列:避免使用键不是递增数字的稀疏数列。稀疏数列中没有包含每个元素的数列称为一个哈希表。访问该数列中的元素会更加耗时。同样地,试着避免预先分配大型数组。最好是随着使用而递增。最后,不要删除数列中的元素。这会让键稀疏。

标记值:V8 用 32 位来表示对象和数字。它使用一位来辨别是对象(flag=1)或者是被称为 SMI(小整数) 的整数(flag=0),之所以是小整数是因为它是 31 位的。之后,如果一个数值比 31 位还要大,V8 将会装箱数字,把它转化为浮点数并且创建一个新的对象来存储这个数字。尽可能试着使用 31 位有符号数字来避免创建 JS 对象的耗时装箱操作。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值