V8 9.x 新特性

1,027 阅读5分钟

v9.9

发布信息

发布时间:2022.01.31

Chrome 同步版本:Chrome 99

链接:V8 release v9.9

JavaScript 新特性

1. Intl.Locale 新增属性

还记得在 v9.5 版本中,新增了 Intl.DisplayNames 的支持类型吗?v9.9 又双叒来扩展 Intl 的 API 啦!

这次扩展的是在 v7.4 引入的Intl.LocaleAPI。

Intl.Locale 对象是为了更便捷地处理 Unicode 区域设置。Unicode 使用字符串作为区域识别标识。区域标识符由语言标识符和扩展标记组成。语言标识符是区域(locale)的核心,包含了语言、脚本和地域子标记(region subtags)。有关区域设置的其他信息体现在可选的扩展标记中。扩展标记保存有关区域设置方面的信息,例如日历类型、时钟类型和编号系统类型。

此次为Intl.Locale对象加入了七个属性:calendars, collations, hourCycles, numberingSystems, timeZones, textInfo, weekInf

其中,访问 calendars, collations, hourCycles, numberingSystems, timeZones这五个属性会返回一个数组,包含该区域标识支持的日历类型、词语定序类型、时钟类型、编号系统类型、时区类型。

const arabicEgyptLocale = new Intl.Locale('ar-EG')
// ar-EG
arabicEgyptLocale.calendars
// ['gregory', 'coptic', 'islamic', 'islamic-civil', 'islamic-tbla']
arabicEgyptLocale.collations
// ['compat', 'emoji', 'eor']
arabicEgyptLocale.hourCycles
// ['h12']
arabicEgyptLocale.numberingSystems
// ['arab']
arabicEgyptLocale.timeZones
// ['Africa/Cairo']

textInfo属性会返回包含区域文字相关信息的对象,目前文字信息只有一个属性 direction, 即表示文字的排版方向,ltr是从左到右,rtl 是从右到左。

arabicEgyptLocale.textInfo
// { direction: 'rtl' }
japaneseLocale.textInfo
// { direction: 'ltr' }
chineseTaiwanLocale.textInfo
// { direction: 'ltr' }

weekInfo 属性会返回当地区域星期相关信息的对象,目前有属性 firstDay 表示一周的开始是周几,1-7 表示周一到周日;weekend 属性返回一个数组,表示周末是哪几天;minimalDays 属性表示每月/每年的第一个星期最少要求的天数。

以下例子中,阿拉伯语地区的一周的开始是周六,周末是周五、周六两天,至少一天出现在该月/该年的星期可作为该月/该年的第一个星期。

arabicEgyptLocale.weekInfo
// {firstDay: 6, weekend: [5, 6], minimalDays: 1}

2. Intl 枚举属性支持的类型

v9.9 也同时新增了 Intl.supportedValuesOf(code) 以返回数组,包含 V8 当前支持的类型。code 参数支持传入calendar, collation, currency,numberingSystem, timeZone, unit

Intl.supportedValuesOf('calendar')
// ['buddhist', 'chinese', 'coptic', 'dangi', ...]

Intl.supportedValuesOf('collation')
// ['big5han', 'compat', 'dict', 'emoji', ...]

Intl.supportedValuesOf('currency')
// ['ADP', 'AED', 'AFA', 'AFN', 'ALK', 'ALL', 'AMD', ...]

Intl.supportedValuesOf('numberingSystem')
// ['adlm', 'ahom', 'arab', 'arabext', 'bali', ...]

Intl.supportedValuesOf('timeZone')
// ['Africa/Abidjan', 'Africa/Accra', 'Africa/Addis_Ababa', 'Africa/Algiers', ...]

Intl.supportedValuesOf('unit')
// ['acre', 'bit', 'byte', 'celsius', 'centimeter', ...]

v9.8

官方无发布blog

v9.7

发布信息

发布时间:2021.11.05

Chrome 同步版本:Chrome 97

链接:V8 release v9.7

JavaScript 新特性

1. 新增 findLast 和 findLastIndex 数组方法

ArrayTypedArray 可以使用 findLastfindLastIndex 方法来从数组尾部开始找到匹配断言的元素了(查看特性解释),比如:

const inputArray = [{v:1}, {v:2}, {v:3}, {v:4}, {v:5}];
inputArray.findLast((element) => element.v % 2 === 0);
// → {v:4}
inputArray.findLast((element) => element.v % 7 === 0);
// → undefined
inputArray.findLastIndex((element) => element.v % 2 === 0);
// → 3
inputArray.findLastIndex((element) => element.v % 7 === 0);
// → -1

v9.6

发布信息

发布时间:2021.10.13

Chrome 同步版本:Chrome 96

链接:V8 release v9.6

WebAssembly 新特性

1. Reference Types 提案

在 v9.6 中发布的 Reference Types 提案允许在 WebAssembly 模块中使用来自 JavaScript 的外部引用。Externref (以前称为 anyref )数据类型提供了保存对 JavaScript 对象的引用的安全方法,并且与 v8 的垃圾收集器完全集成。

已经支持的引用类型的工具链是 AssemblyScriptRust 的 wasm-bindgen

v9.5

发布信息

发布时间:2021.09.21

Chrome 同步版本:Chrome 95

链接:V8 release v9.5

JavaScript 新特性

1. Intl.DisplayNames v2版

在 v8.1 中发布了 Intl.DisplayNames API,支持 language, region, script, 和 currency 类型(查看 API 用法)。现在 v9.5 添加了两个新的支持类型: calendardateTimeField。它们返回不同语言的日历类型和日期时间字段的显示名称:

const frDateTimeFieldNames = new Intl.DisplayNames(['fr'], { type: 'dateTimeField' });
frDateTimeFieldNames.of('month'); // "mois"  法文的月份名称

还增加了对 language 类型的支持,增加了一个新的 languageDisplay 选项,可以是 standarddialgue (默认值) :

const jaDialectLanguageNames = new Intl.DisplayNames(['zh'], { type: 'language' });
const jaStandardLanguageNames = new Intl.DisplayNames(['zh'], { type: 'language' , languageDisplay: 'standard'});
zhDialectLanguageNames.of('en-US')  // "美国英语"
zhDialectLanguageNames.of('en-AU')  // "澳大利亚英语"
zhDialectLanguageNames.of('en-GB')  // "英国英语"

zhStandardLanguageNames.of('en-US') // "英语(美国)"
zhStandardLanguageNames.of('en-AU') // "英语(澳大利亚)"
zhStandardLanguageNames.of('en-GB') // "英语(英国)"

2. 扩展了 timeZoneName 选项

v9.5中的 Intl.DateTimeFormat API 现在支持 timeZoneName 选项的四个新值:

  • shortGeneric:以简短的非位置格式输出时区的名称,例如“ PT ”、“ ET ”等,但不会显示该时区是否属于夏时制。
  • longGeneric:以正常的非位置格式输出时区名称,如“ Pacific Time”、“ Mountain Time”,但不会显示该时区是否属于夏时制。
  • shortOffset:以简短的本地化格林尼治标准时间 GMT 格式输出时区的名称,如“ GMT-8”。
  • longOffset:以简短的本地化格林尼治标准时间 GMT 格式输出时区的名称,如“ GMT-0800”。

WebAssembly新特性

1. 异常处理

V8现在支持 WebAssembly 异常处理(Wasm EH)提案,使用兼容工具链 (例如 Emscripten) 编译的模块可以在 v8 中执行。这个方案相比以前 JavaScript 的解决方案开销较低。

v9.4

发布信息

发布时间:2021.09.06

Chrome 同步版本:Chrome 94

链接:V8 release v9.4

JavaScript 新特性

1. class 支持类静态初始化块

新的类静态初始化块语法,提供了一个单独的位置,来存放给定的类初始化时应该运行一次的代码。

class MyPRNG {
  constructor(seed) {
    console.log('constructor');
    if (seed === undefined) {
      if (MyPRNG.entropyPool.length === 0) {
        throw new Error('Entropy pool exhausted');
      }
      seed = MyPRNG.entropyPool.pop();
    }
    this.seed = seed;
  }

  static entropyPool = [];
  static {
    for (let i = 0; i < 512; i++) {
      this.entropyPool.push(i);
    }
    console.log('static block');
  }
}

可以看到类静态初始化块,在类 MyPRNG 初始化时就进行了块内的计算:

从 v9.4开始,类静态初始化块将不需要 -- harmony-class-static-blocks 标志。

v9.3

发布信息

发布时间:2021.08.09

Chrome 同步版本:Chrome 93

链接:V8 release v9.3

JavaScript 新特性

1. Sparkplug 批量编译

V8 在 v9.1 中发布了超快的新中间层 JIT 编译器 Sparkplug。出于安全原因,V8 write-protectes (W^X) 代码内存生成时,要求在可写 (编译期间) 和可执行之间翻转权限。这是当前使用 mprotect 调用实现的。然而,由于 Sparkplug 生成代码的速度非常快,因此为每个单独的编译函数调用 mprotect 的成本成为编译时间的主要瓶颈。在 V8 v9.3中,我们引入了 Sparkplug 的批量编译: 我们不是单独编译每个函数,而是在批量中编译多个函数。这可以通过每批只翻转一次内存页面权限来分摊这种操作的成本。

批量编译可以减少总的编译时间 (Ignition + Sparkplug) 高达44% ,而无需回溯 JavaScript 的执行。如果我们只看编译 Sparkplug 代码的成本,影响显然更大,例如 Win 10上的 docs_scrolling 基准 (见下文) 减少了82% 。令人惊讶的是,批处理编译比 W^X 的成本提高了更多的编译性能,因为将类似的操作批处理在一起对 CPU 来说更好。在下图中,你可以看到 W^X 对编译时间的影响 (Ignition + Sparkplug)) ,以及批量编译如何减轻这种开销。

2. Object.hasOwn

Object.hasOwnObject.prototype.hasOwnProperty.call 更易记的别名(查看特性解释)。

Object.hasOwn({ prop: 42 }, 'prop')
// → true

3. Error 新增属性 cause

从 v9.3 开始,对各种内置的 Error 构造函数进行了扩展,可以接受第二个参数包含 cause 属性的可选项。如果传递了这样的可选项,则 cause 属性的值将作为 Error 实例上自己的属性。这为错误链提供了一种标准化的方法(查看特性解释):

const parentError = new Error('parent');
const error = new Error('parent', { cause: parentError });
console.log(error.cause === parentError);
// → true
function doWork() {
  try {
    doSomeWork();
  } catch (err) {
    throw new Error('Some work failed', { cause: err });
  }
  try {
    doMoreWork();
  } catch (err) {
    throw new Error('More work failed', { cause: err });
  }
}

try {
  doWork();
} catch (err) {
  switch(err.message) {
    case 'Some work failed':
      handleSomeWorkFailure(err.cause);
      break;
    case 'More work failed':
      handleMoreWorkFailure(err.cause);
      break;
  }
}

本文搬运自我的语雀知识库《技术新动态》,欢迎关注我的语雀个人主页。同时欢迎关注我的掘金专栏,这个专栏将会持续分享学习各种前端/桌面端相关技术(Electron、node.js、V8、Chromium等)的新特性