JavaScript 中的 Tuples 和 Records 是什么?
不变性是我们谈论函数式编程时经常出现的一个常用术语。 这是因为它是其核心原则之一。 当我们谈论不可变对象时,我们只是意味着一旦声明了一个变量,它的值就不能在以后进行更改。 例如:
const presents = ['🎁', '📦', '🎀', '💝', '🎄'];
// --- 可变解决方案 ---
// 我们略过 🎁
// presents 将等价于 ['📦', '🎀', '💝', '🎄'];
presents.shift();
// --- 不可变的解决方案 ---
// newPresents 相当于 📦 🎀 💝 🎄
// presents 依然为 ['🎁', '📦', '🎀', '💝', '🎄'];
const newPresents = presents.slice(1);
第一个解决方案改变了数组,而第二个解决方案创建了一个新的并保持原始数组不变。 在 JavaScript 中,我们没有真正的不可变对象,所以我们要么需要变通方法来实现安全,要么更糟糕的是,我们必须相信人们不会改变这些值。
现在有一个新的 ECMAScript 提案——目前处于第 2 阶段,因此这些实现可以改变——将引入两种新的不可变数据类型:Tuples和 Records。
Tuples(元组)
Tuples 和 Records 都具有相同的语法。 它们可以通过在对象和数组前面使用 #
前缀来定义,如下所示:
// 这是一个正常的数组
const arr = [];
// 这是一个 tuple
const tuple = #[];
使用 Tuples 时,需要注意一些规则:
- 数组中不能有空洞,例如:[1, ,2] 是不允许的;
- 它们只能包含原语或其他 Tuples 和 Records;
- 支持类似于 Arrays 的实例方法,但有一些变化;
例如,改变数组的操作被替换为返回新数组的新操作。 因此,例如:没有 push,我们可以使用 push 来返回一个带有推送值的新元组,或者使用 with 来更改给定索引处的值:
const tuple = #['🍄', '🍅', '🥕'];
// 都返回一个新元组
tuple.pushed('🥒'); // 返回 #['🍄', '🍅', '🥕', '🥒'];
tuple.with(0, '🌳'); // 返回 #['🌳', '🍅', '🥕']
我们还可以使用 Tuple.from() 从现有数组创建元组:
Tuple.from(['🍄', '🍅', '🥕']);
// 同样,我们可以将元组转换为普通数组:
Array.from(tuple);
当然,它们是不可变的,如果尝试更改它们的值或使用非原始值,它们会抛出错误:
const tuples = #['🍄', '🍅', '🥕'];
// TypeError: Callback to Tuple.prototype.map may only return primitives, Records or Tuples
tuples.map(tuple => new Button(tuple));
Records 记录
就像元组一样,记录也用哈希表示:
// 这是一个常规对象
const obj = { ... };
// 这是一个记录
const record = #{
tuple: #['🍄', '🍅', '🥕'] // Records 也会包含 元组(Tuples)
};
处理记录时,我们还需要牢记一些规则:
-
不能在记录中使用
__proto__
标识符 - 方法也是不允许的。 就像元组一样,它们只能包含原语。
要创建新记录,我们还可以选择在使用元组时使用 Record
或 Record.fromEntries
:
const record = Record({
mushroom: '🍄',
tomato: '🍅',
carrot: '🥕'
});
// 或者
const record = Record.fromEntries(#['🍄', '🍅', '🥕']);
而且由于它们是新的数据类型,因此在使用 typeof
运算符时会返回“record”:
typeof #{ ... } // 返回 "record"
typeof #[ ... ] // 返回 "tuple"
总结
除了上面提到的示例之外,我们可以在函数或循环中同时使用记录和元组,就像我们通常使用常规对象一样。
如果你现在想要不可变,最简单的方法是使用 Immutable-js。 还可以使用 Object.freeze 实现部分不变性,但是,它只会冻结直接子级。 因此,我们仍然可以更改深度嵌套的属性:
const obj = Object.freeze({
a: 1,
b: {
c: 2
}
});
// ✅ Won't work
obj.a = 10;
// ❌ Will be changed to 20
obj.b.c = 20;
当然,你也可以通过 plugin-syntax-record-and-tuple
插件将它与 Babel 一起使用。
大家是否已经使用过元组(Tuples)和记录(Records)? 欢迎大家在下面留言一起来讨论!
相关文章
使用 CSS 和 JavaScript 制作文本闪烁
发布时间:2023/04/28 浏览次数:146 分类:CSS
-
本文提供了使用 CSS、JavaScript 和 jQuery 使文本闪烁的详细说明。
在 PHP 变量中存储 Div Id 并将其传递给 JavaScript
发布时间:2023/03/29 浏览次数:69 分类:PHP
-
本文教导将 div id 存储在 PHP 变量中并将其传递给 JavaScript 代码。
在 JavaScript 中从字符串中获取第一个字符
发布时间:2023/03/24 浏览次数:93 分类:JavaScript
-
在本文中,我们将看到如何使用 JavaScript 中的内置方法获取字符串的第一个字符。
在 JavaScript 中获取字符串的最后一个字符
发布时间:2023/03/24 浏览次数:141 分类:JavaScript
-
本教程展示了在 javascript 中获取字符串最后一个字符的方法