Есть ли простой способ полностью заморозить объект и его дочерние элементы в Javascript (Deep Freeze)? - PullRequest
2 голосов
/ 01 июня 2019

Часто вам нужно передать объект в качестве параметра. Функции, обращающиеся к этим объектам, передаются по ссылке и могут изменять исходный объект. Что в зависимости от ситуации может быть нежелательным результатом. Так есть ли способ заморозить объект. Я знаю о Object.freeze()

Но это не влияет на объекты / массивы внутри него.

Например

a = { arr: [1,2,3]}; 
Object.freeze(a);
a.arr.push(4); // still works

Ответы [ 4 ]

1 голос
/ 01 июня 2019

Если вы посмотрите на MDN , там есть функция, которая предлагает функцию deepFreeze, однако она не безопасна для стека. У меня лично есть версия ES5 для асинхронной итерации. Для ES6 что-то в этом направлении может работать, хотя я не проверил это тщательно, хотя:

function deepFreeze(o,promises,oldestParent){
    promises = promises || [];
    oldestParent = oldestParent || o;
    promises.push(
        Promise.resolve().then(function(){
            Object.values(Object.freeze(o)).forEach(function(d,i){
                typeof d === "object" && deepFreeze(d,promises,oldestParent);
            });
            return oldestParent;
        })
    );
    return Promise.all(promises).then((a)=>a[0]);
}

var o = {a:3,b:{test:1,test2:2},c:1};
deepFreeze(o).then(function(x){console.log(x)}); //o is deep frozen

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

1 голос
/ 01 июня 2019

Вы можете сделать очень простое рекурсивное решение, например так:

let a = {
  arr: [1, 2, 3],
  name: "A. Bc"
};

const deepFreeze = o => {
  for (let [key, value] of Object.entries(o)) {
    if (o.hasOwnProperty(key) && typeof value == "object") {
      deepFreeze(value);
    }
  }
  Object.freeze(o);
  return o;
}

deepFreeze(a);

try {
  a.arr.push(4);
} catch(e) {
  console.log("Error: ", e);
}
console.log(a);
0 голосов
/ 03 июня 2019
function deepFreeze(object) {

  // Retrieve the property names defined on object
  var propNames = Object.getOwnPropertyNames(object);

  // Freeze properties before freezing self

  for (let name of propNames) {
    let value = object[name];

    object[name] = value && typeof value === "object" ? 
      deepFreeze(value) : value;
  }

  return Object.freeze(object);
}

let a = { arr: [1,2,3]}; 
deepFreeze(a);
a.arr.push(4); // TypeError: Cannot add property 3, object is not extensible

(второй код [вторая серая зона]) https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze#What_is_shallow_freeze

Спасибо :)

0 голосов
/ 01 июня 2019

Оформить заказ deep-freeze рекурсивно Object.freeze() для объектов

Вот как они это реализуют

function deepFreeze (o) {
  Object.freeze(o);

  Object.getOwnPropertyNames(o).forEach(function (prop) {
    if (o.hasOwnProperty(prop)
    && o[prop] !== null
    && (typeof o[prop] === "object" || typeof o[prop] === "function")
    && !Object.isFrozen(o[prop])) {
      deepFreeze(o[prop]);
    }
  });

  return o;
};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...