Зачем глубокое копирование
Переменные в JS хранятся в памяти в типах значений и ссылочных типах:
Тип значения:
1. Занятое пространство фиксируется и хранится в стеке;
2. Сохраняется и копируется само значение;
3. Базовый тип данных — это тип значения (String, Number, undefined, Boolean, Null);
Тип ссылки:
1. Занятое пространство не фиксируется и хранится в куче;
2. Сохраняется и копируется указатель на объект;
3. Объект, построенный с помощью метода new(), является ссылочным типом;
Таким образом, сложные объекты, такие как Object и Array, необходимо глубоко копировать;
Что не так с глубокой копией JSON.stringify()?
Самый простой способ сделать глубокую копию — использовать JSON.stringify(), сделать глубокую копию, масштабировать:
var obj={
name:'大雄',
age:21
};
var obj1=JSON.parse(JSON.stringify(obj));
Таким образом, с глубоким копированием проблем нет; если у нас есть следующие объекты, как насчет глубокого копирования?
var obj1={
name:'大雄',
say:function(){
console.log('我会说话哦!');
},
birthday:new Date('1990/01/01')
};
var obj2=JSON.parse(JSON.stringify(obj));
console.log(obj2);
// {name: "大雄", birthday: "1989-12-31T16:00:00.000Z"}
Мы видели, что когда в наших объектах есть функции и типы дат, типы дат преобразуются в строки; атрибуты функций просто исчезают! Это большая проблема! После нашего теста мы обнаружили:
- неопределенные, произвольные функции и значения символов игнорируются при сериализации
- Date вызывает toJSON(), чтобы преобразовать его в строку (Date.toISOString()), поэтому он будет рассматриваться как строка.
- Числовые значения в форматах NaN и Infinity и null обрабатываются как null.
- Другие типы объектов, включая Map/Set/WeakMap/WeakSet, будут сериализовать только перечисляемые свойства.
- Выполнение этого метода для объектов, содержащих циклические ссылки (объекты, ссылающиеся друг на друга, образующие бесконечный цикл), вызовет ошибку.
// 下面就是循环引用;
var obj1 = {
x: 1,
y: 2
};
obj1.z = obj1;
var obj2 = JSON.parse(JSON.stringify(obj1)); // 栈溢出,抛出错误;
Поэтому, когда в объекте, который мы хотим клонировать, есть ссылочные типы, мы можем проходить его только рекурсивно, и мы не будем здесь его расширять.
Сколько параметров имеет JSON.stringify()?
JSON.stringify(value[, replacer [, space]])
Мы в основном смотрим, для чего используются второй параметр и третий параметр.
заменитель необязательный
- Если параметр является функцией, во время сериализации каждый атрибут сериализованного значения преобразуется и обрабатывается функцией;
- Если параметр является массивом, только имена свойств, содержащиеся в этом массиве, будут сериализованы в окончательную строку JSON;
- Если этот параметр имеет значение null или не указан, все свойства объекта будут сериализованы;
var obj1={
x:1,
y:2
};
var obj2=JOSN.stringify(obj1,function(key,value){
if(typeof value == 'number'){
return value*2
}
return value;
});
// "{x:2,y:4}"
Давайте еще раз посмотрим на последний параметр:
пробел необязательный
1. Укажите пустую строку для отступа, чтобы украсить вывод (красивая печать)
2. Если параметр является числом, он представляет количество пробелов;
Например
JSON.stringify(obj1,null,'\t');
"{
"x": 1,
"y": 2
}"
I мы используем вкладки для отступов;
Оригинальность не так проста, пожалуйста, ставьте лайк и подписывайтесь, большое спасибо!