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

// A lowercase string
let s = "hello";
// Returns "HELLO", but doesn't modify s
s.toUpperCase();
// => "hello": The original string remains unchanged
s

Примитивные значения сравниваются по значению, то есть два значения считаются равными только в том случае, если их значения одинаковы. Это может показаться запутанным, когда речь идет о числах, логических значениях, значениях NULL и неопределенном значении. Но это довольно просто: например, при сравнении двух разных строк JavaScript считает их равными только тогда, когда они имеют одинаковую длину и каждый символ в одном и том же индексе один и тот же.

(Мягкие навыки для программистов: amazon.com/dp/B0CF599P8J)

С другой стороны, объекты изменяемы; их значения можно изменить:

// Declare an object
let o = { x: 1 };
// Modify: Change the value of one property
o.x = 2;
// Modify: Add a new property
o.y = 3;
​
// Arrays are also mutable
let a = [1, 2, 3];
// Modify: Change the value of an element
a[0] = 0;
// Modify: Add a new element
a[3] = 4;

Объекты не сравниваются по значению; два разных объекта, даже с одинаковыми свойствами и значениями, не считаются равными. Аналогично, два разных массива, даже с одинаковыми элементами в одном и том же порядке, не равны:

// Two objects with the same properties
let o = { x: 1 }, p = { x: 1 };
// => false: Different objects are never equal
o === p
​
// Two different empty arrays
let a = [], b = [];
// => false: Different arrays are never equal
a === b

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

// This variable references an empty array
let a = [];
// Now b references the same array
let b = a;
// Modify the array referenced by variable b
b[0] = 1;
// => 1: The change is visible through variable a as well
a[0]
// => true: a and b reference the same object, so they are equal
a === b

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

// Source array to be copied
let a = ["a", "b", "c"];
// Destination array for copying
let b = [];
// For each index in a[]
for (let i = 0; i < a.length; i++) {
  // Copy elements from a to b
  b[i] = a[i];
}
​
// In ES6, you can use Array.from() to copy an array
let c = Array.from(b);

Если вы хотите сравнить два разных объекта или массива, вы должны сравнить их свойства или элементы. Следующий код определяет функцию, которая сравнивает два массива:

function equalArrays(a, b) {
  // Arrays that reference the same object are equal
  if (a === b) return true;
  // Arrays with different lengths are not equal
  if (a.length !== b.length) return false;
  // Loop through all elements
  for (let i = 0; i < a.length; i++) {
    // If any differences are found, the arrays are not equal
    if (a[i] !== b[i]) return false;
  }
  // Otherwise, the arrays are equal
  return true;
}

(Мягкие навыки для программистов: amazon.com/dp/B0CF599P8J)