翻译本文的目的是尝试给出ECMAScript规范中核心术语的译法,供同好品评。

原文链接:https://v8.dev/blog/understanding-ecmascript-part-1

在这篇文章里,我们会从规范中找一个简单的功能,借以理解规范中的符号。开始吧!

前言

即便你懂JavaScript,阅读其规范也会让人畏缩。

让我们从一个具体的例子开始,然后通过规范去理解它。下面的代码演示了Object.prototype.hasOwnProperty的用法:

const o = { foo: 1 };
o.hasOwnProperty('foo'); // true
o.hasOwnProperty('bar'); // false

o并没有一个叫hasOwnProperty的属性,因此要沿原型链向上查找。于是,在o的原型Object.prototype上找到了它。

为描述Object.prototype.property的工作原理,规范使用了类似伪代码的说明:

Object.prototype.hasOwnProperty(V)

在以参数V调用hasOwnProperty方法时,将执行以下步骤:

  1. P? ToPropertyKey(V)
  2. O? ToObject(this值)
  3. 返回? HasOwnProperty(O, P)

以及

- 阅读剩余部分 -

规范的组织

第5条定义了全规范使用的各种约定

第6-9条定义ECMAScript程序运行的执行环境

第10-16条定义ECMAScript编程语言,包括语法编码及所有语言特性的执行语义。

第17-27条定义ECMAScript标准库,包括ECMAScript程序运行时可以使用的所有标准对象的定义。

第28条描述基于SharedArrayBuffer的内存一致性访问(存取)模型及原子(Atomic)对象方法。

规范术语

译法原文说明
条款clause规范文本的划分,类似章节
机能facility规范指称的特性、能力或机制
实现近似的implementation-approximated由外部资源全部或部分定义的功能,但规范给出了建议的理想行为
实现定义的implementation-defined由本规范的外部资源全部或部分定义的功能
宿主定义的host-defined由本规范的外部资源全部或部分定义的功能
原始值primitive value第6条定义的Undefined、Null、Boolean、BigInt、Symbol或String值
语言实现直接在最低层表示的基准值(datum)
基准值datum
普通对象ordinary object具有基本内部方法(essential internal method)定义的默认行为的对象
异质对象exotic object一个或多个基本内部方法不具有默认行为的对象
(一个对象要么是普通对象,要么是异质对象)
基本内部方法essential internal method普通对象11个内部方法,函数对象2个内部方法
(在JavaScript中,可以通过Reflect API访问。——译者注)
标准对象standard object语义由规范定义的对象
内置对象build-in object实现规定并提供的对象
规范定义的是标准内置对象。实现可以规定并提供其他内置对象。内置构造函数既是内置对象,也是构造函数。
数值Number value原始值,对应双精度64位二进制格式的IEEE754-2019值
数值类型Number type包括NaN、正无穷和负无穷,即所有可能的数值
属性property对象的组成部分,关联一个键(字符串或符号)和一个值
特性attribute用于定义属性性质的内部值
自有属性own property对象直接包含的属性
继承属性inherited property非自有属性,是对象原型(自有或继承)的属性
产生式production
产生式左端left-hand side
产生式右端right-hand side
链式产生式?chain production产生式右端是一个非终结符和零或多个终结符
代换式alternative
目标符goal symbol以唯一非终结符开始的定义
终结符terminator (symbol)
非终结符nonterminator (symbol)
语法文法syntactic grammer:
词法及正则文法lexical and RegExp grammer::
数值字符串文法number string grammer:::
包含文法cover grammar
抽象操作abstract operation
语法导向操作syntax-directed operation
数学操作mathematical operation下标𝔽表示数值(默认数值类型)
下标表示数学值
值表示法value notation语言值以粗体表示,如nulltrue"hello
规范内部值使用无衬线字体,如norma、return或throw
规范类型specification type
列表List规范类型,« 1, 2 »
记录Record规范类型
集合Set规范类型
关系Relation规范类型
完成记录Completion Record规范类型
引用Reference规范类型
基础值base value引用组件
引用名referenced name引用组件
严格引用标志strict reference tag引用组件
超类引用Super Reference
属性描述符Property Descriptor规范类型
环境记录Environment Record规范类型
抽象闭包Abstract Closure规范类型
数据块Data Block
公认符号well-known symbol@@
内部栏位internal slot[[]]
内部方法internal method[[]]
记录字段Record field[[]]
正常完成normal completion (record)[[Type]]为normal
硬性完成abrupt completion (record)[[Type]]为throw、return、continune或break
环境记录environment record
声明环境记录declarative environment record
对象环境记录object environment record
全局环境记录global environment record
领域realm
执行上下文execution context
执行上下文栈execution context stack
运执上下文running execution context
代理agent即用户代理(User-Agent)的代理
agent cluster
forward progress
静态语义static semantic
前期错误early error

原文地址:https://2ality.com/2020/05/records-tuples-first-look.html

原文作者:Dr. Axel Rauschmayer

Dr. Axel Rauschmayer最近撰文介绍了还处于Stage1阶段的两个JavaScript新特性:记录和元组。

记录和元组是一个新提案(Record & Tuple,https://github.com/tc39/proposal-record-tuple),建议为JavaScript增加两个复合原始类型:

  • 记录(Record),是不可修改的按值比较的对象
  • 元组(Tuple),是不可修改的按值比较的数组

什么是按值比较

当前,JavaScript只有在比较原始值(如字符串)时才会按值比较(比较内容):

> 'abc' === 'abc'
true

但在比较对象时,则是按标识比较(by identity),因此对象只与自身严格相等:

> {x: 1, y: 4} === {x: 1, y: 4}
false
> ['a', 'b'] === ['a', 'b']
false

“记录和元组”的提案就是为了让我们可以创建按值比较的复合类型值。

比如,在对象字面量前面加一个井号(#),就可以创建一个记录。而记录是一个按值比较的复合值,且不可修改:

> #{x: 1, y: 4} === #{x: 1, y: 4}
true

如果在数组字面量前面加一个#,就可以创建一个元组,也就是可以按值比较且不可修改的数组:

> #['a', 'b'] === #['a', 'b']
true

按值比较的复合值就叫复合原始值或者复合原始类型

记录和元组是原始类型

使用typeof可以看出来,记录和元组都是原始类型:

> typeof #{x: 1, y: 4}
'record'
> typeof #['a', 'b']
'tuple'

记录和元组的内容有限制

  • 记录:

    • 键必须是字符串
    • 值必须是原始值(包括记录和元组)
  • 元组:

    • 元素必须是原始值(包括记录和元组)

把对象转换为记录和元组

> Record({x: 1, y: 4}) 
#{x: 1, y: 4}
> Tuple.from(['a', 'b'])
#['a', 'b']

注意:这些都是浅层转换。如果值树结构中有任何节点不是原始值,Record()和Tuple.from()会抛出异常。

- 阅读剩余部分 -

原文:https://davidflanagan.com/2020/05/12/javascript-to-forget.html

作者:David Flanagan

JavaScript这门语言的第一个演示版差不多就在25年前诞生。

没记错的话,25年前的今天,1995年5月10日,星期三,我刚刚过了创造JavaScript(代号为“Mocha”)的“5月的10天”冲刺的一半。我正在写下个周一就要交付的一个演示,目的是展示JS与Netscape的深度浏览器集成(相对于Java小应用)。

1995年秋天,这门语言在Netscape Navigator的一个测试版中发布,当时叫LiveScript。那一年的年底,又被改名为JavaScript。也是在那一年,David Flanagan开始写JavaScript: The Definitive Guide的第一版,并由O'Reilly在1996年8月出版。如今,24年过去了。

犀牛书(英文版)第7版再过几个星期就要面世了。为此,David回忆了一下,想告诉大家有哪些JavaScript特性可以放心地忘掉。一个原因是第七版比第6版薄了不少。而这主要是因为之前的很多东西2020年的开发者已经不用关心了。Web兼容性永远存在(至少25年以来一直如此),浏览器厂商可能在很长时期内仍然需要支持那些陈旧的、难以理解的语言和平台特性。但对我们而言,已经没有必要再为这些特性分心了。

也就是说,有不少JavaScript和Web平台特性在第7版里已经销声匿迹了。应该说,能对这些特性说再见是件高兴的事。以下就是David凭记忆列出的几个应该忘记的特性。

  • arguments对象已经被ES6的...args语法完全取代。要解释清楚arguments与命名参数的关系,以及始终注意它对性能的影响着实不易。在遗留的前端代码中,也许还会看到它的身影。在严格模式下如果想将局部变量或函数参数命名为arguments,那浏览器也会提醒你它的存在。不过现在有了剩余参数,它就应该悄悄地被人遗忘了。
  • 曾几何时,我们还会担心重复拼接字符串导致的性能问题。有一段时间,大家都学会了先把字符串推到数组里,最后再使用join()把它们拼接起来。后来,JavaScript变快了,我们就把这个模式给忘了。而现在有了模板字面量,谁还会再拼接字符串呢?
  • document.write()在很早以前,确切地说是在DOM问世之前,曾经是JavaScript中最重要的特性。(如果你没在20世纪写过JavaScript,那可能想象不到DOM出现之前的日子,但那个时代真的存在过。)如果没记错的话,人们甚至可以使用document.write()向文档中插入脚本。不过这时候要小心,因为你得把末尾的</script>标签拆成两个字符串。这样HTML解析器才不会把它解释为当前运行脚本的结束标签。
  • HTML早期是没有<iframe>的,不过有<frameset><frame>window.frames属性是一个数组,包含嵌套的window对象,表示文档中的窗格。实际上,可以在窗格中调用文档的open()方法,然后使用document.write()在该窗格中动态生成整个文档。不管怎么说,这还真有点酷。因为窗格可以嵌套在其他窗格中,每个window对象都有一个frames数组包含自己的子窗格、一个parent属性引用包含窗口和一个top属性引用顶级窗口。犀牛书的早期版本专门用了几节篇幅和复杂的示意图来解释这些内容。
  • 在文档中直接引用特定元素的技术基本上都废弃了。前面说到的frames数组是一个,没记错的话,还有linksimages数组,包含文档中的所有链接和所有图片。IE(我记得应该是版本4)一步到位,引入了document.all,这是一个包含文档中所有元素的数组。(这也是“DHTML”也就是“动态HTML”及后来DOM的发端,有点像人类进化史上第一条爬上陆地的鱼。)document.all有各种各样新奇的特性,它这个数组本身还有很多按名字或按其他条件来查询元素的方法。document.all最终没有被写进标准,但即便是标准的document.getElementById()document.getElementsByName()document.getElementsByTagName()docuemnt.getElementsByClassName()方法,在今天看来似乎也已经没多少人用了。因为受到了jQuery的$()及受它启发而引入标准的document.querySelector()document.querySelectorAll()的排挤。借用CSS选择符的威力,这两个方法直接就把之前的那些方法都给废掉了。
  • 说起我最恨Internet Explorer的一件事,就是他们非要使用attachEvent()来注册事件处理程序。在我的印象中,他们是在标准已经规定了addEventListener()方法之后这么搞的,这可真是太讨厌了。事件及其处理程序一直以来都是Web开发中一个最大的不兼容问题。多少年以来,JavaScript程序员(和JavaScript图书作者)都必须处理IE事件模型与标准事件模型的各种差异。为此,处理事件的代码必须写两遍,一遍针对IE,一遍针对Firefox。书中介绍事件的章节相应地也会两倍长,因为有两套非常相似但却完全不兼容的事件处理机制。jQuery的一个主要特性就是实现了自己的事件兼容层,于是开发者只需掌握一种事件处理方式即可。我怀疑这也是它快速流行的一个重要原因。
  • 最初的DOM API是在人们疯狂迷恋XML的时代定义的。(当时的人们确实相信用不了几年,XML就可以解决所有数据问题。真是个难以置信的时代。)某种程度上,正是W3C的认可,才让Java那些人影响了DOM API,这些人觉得最好只定义一套API,JavaScript程序员能用它操作HTML文档,而Java程序员能用它操作XML数据。这也是为什么会有Attr节点(最好当它不存在)这么怪异的东西的原因。DOM Level 3 API中最让我不理解的一个操作是从文档中删除元素e,你不能像今天这样写成e.remove(),而是必须写成e.parentNode.removeChild(e)。

不管怎么说,现在都已经2020年了。犀牛书第7版将不会再花笔墨描述这些陈旧的特性,这些特性大家最好还是忘掉。

原文地址:https://blog.logrocket.com/deno-1-0-what-you-need-to-know/

原文作者:David Else

经过近两年的等待,官方正式宣布Deno 1.0将于5月13日发布。如今,API已经冻结,倒计时开始。

借助创始人的大名,加之其前瞻性愿景,Deno的发布无疑是近期最激动人心也最具争议性的JavaScript话题。

Deno是通用JavaScript/TypeScript编程环境,集成了很多最好的开源技术,在一个小执行文件中提供了全面的解决方案。

作为Node.js的创始人,Ryan Dahl又打造了Deno。Deno利用了2009年Node.js发布之后JavaScript的新增特性,同时也解决了Ryan在其“Node.js十大遗憾”(演讲)中提到的设计缺陷。有人称其为Node.js的后续者,但作者本人并没有这么说过。

与Node.js使用C++不同,Deno是使用Rust开发的,构建在Tokio(https://tokio.rs/,Rust异步运行时)平台之上。但与Node.js类似,Deno也使用V8引擎运行JavaScript。内置TypeScript是Deno的是一个明显特征。尽管需要先编译成JavaScript再运行,但这个过程在内部完成,因此看起来就像Deno原生支持TypeScript一样。

1. 上手

根据官网主页(https://deno.land/)的指导,可以下载Deno。要升级到新版本,运行deno upgrade。如果你之前安装的Deno版本过低,可以尝试再次运行终端脚本安装。

要了解Deno子命令,使用如下任意一命令。

  • deno [subcommand] -h:显示摘要
  • deno [subcommand] --help:显示详细信息

本文将介绍Deno 1.0的重点特性,包括使用最新语法应用这些特性的示例。我们会尽可能使用TypeScript,等价的JavaScript当然也没问题。

相信看完这篇文章你一定会喜欢上Deno。本文将正式带领读者进入Deno开发的大门。

- 阅读剩余部分 -