«Замораживание» массивов в Javascript? - PullRequest
30 голосов
/ 22 сентября 2011

Поскольку в спецификации ECMA-262 Javascript получил метод Object.freeze () , который позволяет использовать объекты, свойства которых нельзя изменять, добавлять или удалять.

var obj = {'a':1, 'b:2'};
Object.freeze(obj);
Object.isFrozen(obj);       // returns true
obj.a = 10;                 // new assignment has no affect
obj.a;                      // returns 1

Пока все хорошо.

Мне интересно, должно ли freeze () работать и с массивами.

var arr = [1, 2];
Object.freeze(arr);
Object.isFrozen(arr);      // returns true
arr[0] = 10;
arr;                       // returns [10, 2] ... ouch!

Возможно, я ошибаюсь, но у меня сложилось впечатление, что Array наследуется от Object.

typeof obj                 // "object"
typeof arr                 // "object"

Любые идеи, указатели, просветления будут высоко оценены.

Ответы [ 2 ]

32 голосов
/ 22 сентября 2011

Да, заморозка должна работать для массивов, поведение, которое вы испытываете, явно является ошибкой реализации.

Эта ошибка может быть связана с тем, что объекты массива реализуют собственный внутренний метод [[DefineOwnProperty]] (магия, которая заставляет свойство length работать).

Я только что протестировал его на двух реализациях, и он работает правильно (Chrome 16.0.888 и Firefox Aurora 8.02a).

По поводу вашего второго вопроса, ну, объекты массива наследуются от Array.prototype, который наследуется от Object.prototype, например, вы можете получить доступ к не затененным методам из Object.prototype непосредственно для объектов массива:

['a'].hasOwnProperty('0'); // true

Но это не связано с тем, как работает typeof, этот оператор вернет 'object' для любого экземпляра объекта, независимо от его вида, и для значения null, на которое люди всегда жаловались.

Остальные возможные возвращаемые значения оператора typeof соответствуют примитивным типам языка: Number, String, Boolean, Symbol и Undefined.

0 голосов
/ 18 марта 2019

Вместо заморозки используйте оператор распространения, чтобы копировать вещи без их изменения (если вы, конечно, используете транспортер):

const second = {
  ...first,
  test: 20
}
...