Новые неизменяемые типы данных JavaScript: записи и кортежи

Записи и кортежи — это новые неизменяемые типы данных JavaScript, которые в настоящее время находятся на этапе 2 процесса утверждения стандартов TC39. Они могут быть изменены и в настоящее время недоступны ни в одном браузере или во время выполнения, но рабочие реализации должны появиться в течение следующего года. Они помогают решить пару запутанных головоломок, с которыми сталкиваются программисты…

Постоянные изменения

Профессиональные JavaScripters скажут вам, что constлучше всего назначать переменные с помощью. Это делает переменные неизменными. Значения нельзя изменить, поэтому у вас будет меньше проблем.

К сожалению, constнеизменными становятся только примитивные значения (String, Number, BigInt, Boolean, Symbol и undefined). Вы не можете переназначить массив или объект, но значения и свойства, которые они содержат, можно изменить. Например:

// array constant
const myArray = [1, 2, 3];

// change array values
myArray[0] = 99;
myArray.push(42);

console.log(myArray); // [ 99, 2, 3, 42 ]

myArray = 'change'; // ERROR!

Аналогично для объектов:

// object constant
const myObj = { a: 1, b: 2, c: 3 }

// change object properties
myObj.a = 99;
myObj.d = 42;

console.log(myObj); // { a:99 ,b:2, ,c:3, ,d:42 }

myObj = 'change'; // ERROR!

Object.freeze()Метод может помочь, но только мелкое замораживание применяется для непосредственных дочерних свойств объекта:

const myObj = { a: 1, b: 2, c: { v: 3 } }
Object.freeze(myObj);

myObj.a = 99; // silently ignored
myObj.c.v = 99; // works fine

console.log(myObj); // { a: 1, b: 2, c: { v: 99 } }

Поэтому трудно гарантировать, что функция намеренно или случайно не изменит значения, хранящиеся в массиве или объекте. Разработчики должны либо надеяться на лучшее, либо передавать клонированную версию переменной (что имеет свои проблемы).

Эквивалентное неравенство

Дальнейший хаос может возникнуть, когда разработчики попытаются произвести кажущиеся разумными сравнения объектов или массивов:

const str = 'my string';
console.log( str === 'mystring' );  // true

const num = 123;
console.log( num === 123 );         // true

const arr = [1, 2, 3];
console.log( arr === [1, 2, 3] );   // false

const obj = { a: 1 };
console.log( obj === { a: 1 } );    // false

По значению можно сравнивать только примитивные типы. Объекты и массивы передаются и сравниваются по ссылке. Две переменные будут эквивалентны, только если они указывают на один и тот же элемент в памяти:

const a = [1, 2];

const b = a;
b.push(3);

console.log( a === b ); // true

// original array has changed
console.log( a ); // [1, 2, 3]

Для глубокого сравнения двух объектов или массивов требуется функция рекурсивного сравнения для оценки каждого значения по очереди. Даже в этом случае вы можете столкнуться с проблемами с такими типами, как даты или функции, которые могут храниться по-разному.

Кортежи: неизменяемые структуры данных, подобные массивам

Кортежи — это глубоко неизменяемые структуры данных, подобные массивам. По сути, они представляют собой составные примитивные типы, идентифицируемые с помощью #модификатора перед синтаксисом нормального массива:

// new tuples
const t1 = #[1, 2, 3];
const t2 = #[1, 2, #[3, 4]];

В качестве альтернативы новый Tuple.from()метод может создать кортеж из массива:

// new tuple from an array
const t3 = Tuple.from( [1, 2, 3] );

В отличие от стандартных массивов, кортежи должны удовлетворять следующим требованиям:

  1. У них не должно быть отверстийс неустановленными значениями. Например, #[1,,,4]неверно.
  2. Они должны устанавливать только примитивы, другие кортежи или записи. Типы, такие как массивы, объекты или функции, не разрешены:
  const t4 = #[ new Date() ]; // ERROR (sets an object)
  const t5 = #[1, 2, [3, 4]]; // ERROR (sets an array)

Поскольку кортежи являются примитивами, их можно глубоко сравнить по значению с другими кортежами:

const t6 = #[1, 2];

console.log( t6 === #[1, 2] ); // true

Обратите внимание, что сравнения с использованием менее строгого ==оператора возможны, если кортеж содержит одно значение. Например:

const t7 = #[99];

console.log( t7 == #[99] ); // true
console.log( t7 == 99 );    // true
console.log( t7 == '99' );  // true

// tuple cannot be compared to an array
console.log( t7 == [99] );  // false

Записи: неизменяемые объектные структуры данных

Записи — это глубоко неизменяемые объектные структуры данных. Опять же, это составные примитивные типы, идентифицируемые с помощью #модификатора перед синтаксисом нормального объекта:

// new records
const r1 = #{ a: 1, b: 2 };
const r2 = #{
  a: 1,
  b: #{ c: 2 }, // child record
  d: #[ 3, 4 ]  // child tuple
};

В качестве альтернативы новый Record()конструктор может создать запись из объекта:

// new record from an object
// #{ a: 1, b: 2 }
const r3 = Record({ a: 1, b: 2 });

Или Record.fromEntries()метод может создать запись из серии пар значений массива или кортежа:

// new record from array of name-values
// #{ a: 1, b: 2 }
const r4 = Record.fromEntries([
  ['a', 1],
  ['b', 2]
]);

В отличие от стандартных объектов, записи должны соответствовать следующим требованиям:

  1. Они должны использовать строковые имена свойств. Например, #{ Symbol(): 1 }неверно.
  2. Они должны устанавливать значения только с помощью примитивов, других кортежей или записей. Типы, такие как массивы, объекты или функции, не разрешены:
  const r5 = #{ 'd': new Date() };   // ERROR (sets an object)
  const r6 = #{ a: 1, b: { c: 2 } }; // ERROR (sets an object)

Записи можно глубоко сравнивать с другими записями, и порядок свойств не имеет значения:

const r7 = #{ a: 1, b: 2 };

console.log( r7 === #{ b: 2, a: 1 } ); // true

Записи можно сравнивать только с другими записями, поэтому использование оператора ==или ===не имеет значения. Однако можно извлечь объект keys()и values()для конкретных сравнений. Например:

const r8 = #{ a: 99 };

console.log( Object.values(r8) == 99 ); // true

Неизменяемые обновления

Кортежи и записи могут звучать как сложные термины информатики, но они, наконец, позволят надёжное неизменяемое хранение данных и сравнения в JavaScript.aScript.

 

Читайте также:  Как изучить Node.js: руководство по началу работы
Оцените статью
bestprogrammer.ru
Добавить комментарий