JavaScript 新增原始数据类型:Record 与 Tuple 详解

作者:异步漫步

时间:2026-10-24

浏览:626

本文详细介绍JavaScript提案中新增的两种原始数据类型:Record和Tuple。Record对应只读对象,Tuple对应只读数组,语法以#开头。文章解析了其不可变性、基于值的相等性比较优势,以及通过Babel插件进行环境配置和编译的实际操作步骤,帮助开发者提前体验这一特性。

文章目录

前言

JavaScript语言规范中正在推进两项新的数据类型提案:Record和Tuple。Record本质上是一个只读的对象(Object),而Tuple则是只读的数组(Array)。在其他编程语言如Python中,类似的概念已经存在,例如Python中的Tuple通常指代不可变的列表结构。该提案目前处于第2阶段(Stage 2),意味着其标准化进程较为成熟。对于希望提前在项目中尝试该特性的开发者,文末提供了使用polyfill的具体教程。

基础写法

// Records
const myRecord = #{
 name: '01',
  age: 23
}

// Tuple
const myTuple = #['1', '2', '3']

在语法层面,定义Record和Tuple非常简单,只需在原有的对象字面量或数组字面量前添加井号(#)前缀即可。

可读特性

Record和Tuple的声明语法与标准的对象和数组保持一致,但它们在行为上存在关键差异。

const myRecord = #{
 name: '01'
}

const myTuple = #['1', '2']

myRecord['age'] = 23  // error
myTuple.push('3')  // error

如果在尝试修改Record或Tuple的属性或元素时,控制台会抛出错误。这正是前文提到的核心特性:Record和Tuple是不可变的(只读)的数据结构,任何试图修改其内部内容的操作都会导致程序报错。

非唯一性

在常规JavaScript开发中,使用全等运算符(===)直接比较两个不同的对象或数组通常返回false。这是因为对象和数组是引用类型,每次创建都会在内存中分配新的地址,即使内容完全相同,地址也不同。

const obj1 = { name: '01' }
const obj2 = { name: '01' }
const objIsSame = obj1 === obj2   // false

const arr1 = [1]
const arr2 = [1]
const arrIsSame = arr1 === arr2   // false

为了判断两个普通对象或数组的内容是否完全一致,通常需要编写递归遍历函数进行深度比较。Record和Tuple的引入旨在解决这一痛点,通过基于值的比较机制,简化相等性判断的逻辑。

const record1 = #{ name: '01' }
const record2 = #{ name: '01' }
const recordIsSame = record1 === record2   // true

const tuple1 = #[1]
const tuple2 = #[1]
const tupleIsSame = tuple1 === tuple2   // true

实验结果表明,只要Record或Tuple内部包含的数据内容一致,无论它们是在代码中分开创建还是通过不同路径生成,使用===运算符进行比较时都会返回true。这实现了基于值的相等性语义。

普通对象和数组的转换

开发者可以使用Record()构造函数将普通对象转换为Record类型,同样可以使用Tuple()构造函数将普通数组转换为Tuple类型。这种转换方式提供了从传统数据结构向新类型过渡的途径。

const myRecord = Record({ name: '01', age: 23 });   // #{ name: '01', age: 23 }
const myTuple = Tuple([1, 2, 3, 4, 5]);   // #[1, 2, 3, 4, 5]

支持扩展运算符

Record和Tuple完全支持JavaScript的扩展运算符(...)。这使得在创建新的Record或Tuple时,可以方便地合并现有数据并添加新元素,同时保持其不可变特性。

const myTuple = #[1, 2, 3];
const myRecord = #{ name: '01', age: 23 };

const newRecord = #{ ...myRecord, money: 0 } // #{ name: '01', age: 23, money: 0 }
const newTuple = #[ ...myTuple, 4, 5];   // #[1, 2, 3, 4, 5]

JSON方法扩展

除了现有的JSON.parse和JSON.stringify方法外,相关提案草案中曾提议为JSON对象新增parseImmutable方法。该方法的功能预期是直接解析字符串格式的Record或Tuple数据,并将其转换为对应的不可变对象实例,从而简化序列化与反序列化的过程。

提前体验

若想在当前环境中体验Record和Tuple功能,可以通过安装Babel的相关插件来实现。

# babel基本的库
yarn add @babel/cli @babel/core @babel/preset-env -D

# Record和Tuple Babel polyfill
yarn add @babel/plugin-proposal-record-and-tuple @bloomberg/record-tuple-polyfill -D

在项目根目录下创建名为.babelrc的配置文件,并写入以下配置内容:

{
    "presets": ["@babel/preset-env"],
    "plugins": [
        [
          "@babel/plugin-proposal-record-and-tuple",
          {
            "importPolyfill": true,
            "syntaxType": "hash"
          }
        ]
      ]
}

接着创建名为index.js的入口文件,编写测试代码:

const tuple1 = #[1,2,3]
const tuple2 = #[1,2,3]

const record1 = #{ name: '01' }
const record2 = #{ name: '02' }

console.log(tuple1 === tuple2, record1 === record2)

在终端中执行Babel编译命令,将源代码转换为兼容当前环境的JavaScript代码:

./node_modules/.bin/babel index.js --out-file compiled.js

编译完成后,生成的compiled.js文件内容如下所示:

"use strict";

var _recordTuplePolyfill = require("@bloomberg/record-tuple-polyfill");

var tuple1 = (0, _recordTuplePolyfill.Tuple)(1, 2, 3);
var tuple2 = (0, _recordTuplePolyfill.Tuple)(1, 2, 3);
var record1 = (0, _recordTuplePolyfill.Record)({
  name: '01'
});
var record2 = (0, _recordTuplePolyfill.Record)({
  name: '02'
});
console.log(tuple1 === tuple2, record1 === record2);

最后,运行编译后的compiled.js文件,即可在控制台查看运行结果。

node compiled.js
# Result: true false

关于@babel/plugin-proposal-record-and-tuple插件的更多配置选项和用法,请参考Babel官方文档。

https://babeljs.io/docs/en/babel-plugin-proposal-record-and-tuple#docsNav

应用场景

理解了Record和Tuple的核心特性后,最显著的特点是其“只读”属性。基于这一不可变性,我们可以探讨其在实际开发中的具体应用场景。

  • 首先,Record和Tuple可用于保护敏感或关键数据,例如函数的返回值、对象内部的静态属性等,防止外部代码意外修改这些数据结构。

  • 其次,由于Record和Tuple具有基于值的相等性且不可变,它们非常适合作为JavaScript对象的键(key)使用。这解决了传统对象作为键时因引用地址不同而导致的查找困难问题。

总结

本文介绍了JavaScript新增的Record和Tuple两种原始数据类型。通过了解其语法、只读特性及比较优势,开发者可以更好地利用这些新特性优化代码结构。如需了解更多关于JS新增原始数据类型的技术细节,建议查阅本站过往文章或持续关注后续相关教程,感谢支持。

实用工具推荐

电子包浆

绿化、压缩、噪点和虚拟水印,自由调节做旧程度。

使用 ›
图片压缩

选择画质和输出格式,预览压缩前后的大小。

使用 ›
相关文章