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 =>newButton(tuple));

Records 记录

就像元组一样,记录也用哈希表示:

// 这是一个常规对象

const obj = { ... };

// 这是一个记录

const record = #{

tuple: #['????', '????', '????'] // Records 也会包含 元组(Tuples)

};

处理记录时,我们还需要牢记一些规则:

  • 不能在记录中使用 __proto__ 标识符
  • 方法也是不允许的。 就像元组一样,它们只能包含原语。

要创建新记录,我们还可以选择在使用元组时使用 RecordRecord.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)? 欢迎大家在下面留言一起来讨论!

本文转载自:迹忆客(https://www.jiyik.com)

以上是 JavaScript 中的 Tuples 和 Records 是什么? 的全部内容, 来源链接: utcz.com/z/290315.html

回到顶部