предисловие
На самом деле, есть много полезных вещей, которые я узнал и запомнил в свое время, но я не могу вспомнить их спустя долгое время, поэтому я не могу вспомнить оригинальные вещи, которые можно использовать таким образом в ежедневной разработке. , а я выбираю более сложный и хлопотный путь. На самом деле, знания, которые мы изучаем каждый день, предназначены для использования, и даже если вы запомните пункт знания сегодня, не задумываясь о том, для чего мы можем использовать этот пункт знания, вы постепенно забудете его через несколько дней. Итак, сегодня мы взглянем на то, чего вы не знаете, что вы упускаете, забываете или о чем не думаете в своем ежедневном изучении.JSON.stringify()
сила.
Обучение по требованиюJSON.stringify()
В первую очередь с такой необходимостью обработки данных мы столкнулись в процессе разработки
const todayILearn = {
_id: 1,
content: '今天学习 JSON.stringify(),我很开心!',
created_at: 'Mon Nov 25 2019 14:03:55 GMT+0800 (中国标准时间)',
updated_at: 'Mon Nov 25 2019 16:03:55 GMT+0800 (中国标准时间)'
}
Нам нужно обработать вышеуказанный объект в следующий объект
const todayILearn = {
id: 1,
content: '今天学习 JSON.stringify(),我很开心!',
createdAt: 'Mon Nov 25 2019 14:03:55 GMT+0800 (中国标准时间)',
updatedAt: 'Mon Nov 25 2019 16:03:55 GMT+0800 (中国标准时间)'
}
То есть изменить свойство объекта без изменения значения свойства. Пучок_id
изменить наid
,Пучокupdated_at
изменить наupdatedAt
,Пучокcreated_at
изменить наcreatedAt
. Давайте теперь посмотрим на это небольшое требованиеJSON.stringify()
Это мощно.
Чтобы сначала решить эту проблему, у нас есть много решений, мы сначала предлагаем два неэлегантных решения:
- Вариант 1: Один обход + еще одно объявление переменной
// 多一个变量存储
const todayILearnTemp = {};
for (const [key, value] of Object.entries(todayILearn)) {
if (key === "_id") todayILearnTemp["id"] = value;
else if (key === "created_at") todayILearnTemp["createdAt"] = value;
else if (key === "updatedAt") todayILearnTemp["updatedAt"] = value;
else todayILearnTemp[key] = value;
}
console.log(todayILearnTemp);
// 结果:
// { id: 1,
// content: '今天学习 JSON.stringify(),我很开心!',
// createdAt: 'Mon Nov 25 2019 14:03:55 GMT+0800 (中国标准时间)',
// updated_at: 'Mon Nov 25 2019 16:03:55 GMT+0800 (中国标准时间)'
// }
Вариант 1 не вызывает никаких проблем и может быть реализован. Но объявляется еще одна переменная и добавляется еще один цикл, и еще много чегоif
else
Предложение не кажется очень элегантным.
- Вариант 2: Насилие
delete
Атрибуты и добавленные атрибуты
// 极致的暴力美学
todayILearn.id = todayILearn._id;
todayILearn.createdAt = todayILearn.created_at;
todayILearn.updatedAt = todayILearn.updated_at;
delete todayILearn._id;
delete todayILearn.created_at;
delete todayILearn.updated_at;
console.log(todayILearn);
// 太暴力😢
//{
// content: '今天学习 JSON.stringify(),我很开心!',
// id: 1,
// createdAt: 'Mon Nov 25 2019 14:03:55 GMT+0800 (中国标准时间)',
// updatedAt: 'Mon Nov 25 2019 16:03:55 GMT+0800 (中国标准时间)'
//}
Решение прямого перебора с удалением слишком грубое и имеет недостаток, заключающийся в изменении порядка свойств.
- Решение 3. Сериализация +
replace
Эстетический образец
const mapObj = {
_id: "id",
created_at: "createdAt",
updated_at: "updatedAt"
};
JSON.parse(
JSON.stringify(todayILearn).replace(
/_id|created_at|updated_at/gi,
matched => mapObj[matched])
)
// {
// id: 1,
// content: '今天学习 JSON.stringify(),我很开心!',
// createdAt: 'Mon Nov 25 2019 14:03:55 GMT+0800 (中国标准时间)',
// updatedAt: 'Mon Nov 25 2019 16:03:55 GMT+0800 (中国标准时间)'
// }
Мгновенно чувствовать себя очень элегантно и комфортно, есть дерево!
Далее начинается основной фильм, его мы сегодня планомерно изучим или пересмотримJSON.stringify
Базовые знания позволяют нам быть более непринужденными в ежедневном развитии.
JSON.stringify()
Девять характеристик
JSON.stringify()
Первая главная особенность
дляundefined
, любую функцию иsymbol
Когда в качестве значения свойства объекта, элемента массива и отдельного значения используются три специальных значенияJSON.stringify()
вернет разные результаты.
Во-первых, давайте рассмотрим точки знаний и рассмотрим очень простой вопрос интервью: что выведет следующий код?
const data = {
a: "aaa",
b: undefined,
c: Symbol("dd"),
fn: function() {
return true;
}
};
JSON.stringify(data); // 输出:?
// "{"a":"aaa"}"
Это очень просто.Основные точки знаний, которые проверяет интервьюер по этой теме:
-
undefined
, любую функцию иsymbol
как значение свойства объектаJSON.stringify()
пропустит (игнорирует) их сериализацию
Интервьюер спрашивает: предполагатьundefined
, любую функцию иsymbol
А как насчет значений в качестве элементов массива?
JSON.stringify(["aaa", undefined, function aa() {
return true
}, Symbol('dd')]) // 输出:?
// "["aaa",null,null,null]"
Очки знаний:
-
undefined
, любую функцию иsymbol
Как значение элемента массива,JSON.stringify()
будет сериализовать их какnull
Давайте немного подумаем, каков будет результат сериализации этих значений по отдельности?
JSON.stringify(function a (){console.log('a')})
// undefined
JSON.stringify(undefined)
// undefined
JSON.stringify(Symbol('dd'))
// undefined
Результатом отдельных преобразований является:
-
undefined
, любую функцию иsymbol
одеялоJSON.stringify()
возвращается при сериализации как отдельное значениеundefined
JSON.stringify()
Краткое изложение первой основной функции
-
undefined
, любую функцию иsymbol
как значение свойства объектаJSON.stringify()
сериализовать пропустить (игнорировать) их -
undefined
, любую функцию иsymbol
В качестве значения элемента массиваJSON.stringify()
будет сериализовать их какnull
-
undefined
, любую функцию иsymbol
одеялоJSON.stringify()
При сериализации как отдельное значение оба возвращаютundefined
JSON.stringify()
Вторая главная особенность
Это также момент, на который следует обратить внимание при использовании:
- Не гарантируется, что свойства объектов, не являющихся массивами, появятся в сериализованной строке в определенном порядке.
const data = {
a: "aaa",
b: undefined,
c: Symbol("dd"),
fn: function() {
return true;
},
d: "ddd"
};
JSON.stringify(data); // 输出:?
// "{"a":"aaa","d":"ddd"}"
JSON.stringify(["aaa", undefined, function aa() {
return true
}, Symbol('dd'),"eee"]) // 输出:?
// "["aaa",null,null,null,"eee"]"
Как мы сказали в первой функции,JSON.stringify()
Некоторые специальные значения игнорируются при сериализации, поэтому нет гарантии, что сериализованная строка все равно будет отображаться в определенном порядке (кроме массивов).
JSON.stringify()
Третья характеристика
- Преобразовать значение, если оно есть
toJSON()
функция, какое значение возвращает функция, каково значение сериализованного результата, а значения других свойств игнорируются.
JSON.stringify({
say: "hello JSON.stringify",
toJSON: function() {
return "today i learn";
}
})
// "today i learn"
JSON.stringify()
Четвертая характеристика
-
JSON.stringify()
сериализуется нормальноDate
ценность .
JSON.stringify({ now: new Date() });
// "{"now":"2019-12-08T07:42:11.973Z"}"
ФактическиDate
Развертывание самого объектаtoJSON()
метод (такой же, как Date.toISOString()), поэтомуDate
Объекты обрабатываются как строки.
JSON.stringify()
Пятая характеристика
-
NaN
а такжеInfinity
значение формата иnull
будет рассматриваться какnull
.
Прямой код:
JSON.stringify(NaN)
// "null"
JSON.stringify(null)
// "null"
JSON.stringify(Infinity)
// "null"
JSON.stringify()
Шестая характеристика
Что касается сериализации примитивных типов:
- Булевы, числовые и строковые объекты-обертки автоматически преобразуются в соответствующие примитивные значения во время сериализации.
JSON.stringify([new Number(1), new String("false"), new Boolean(false)]);
// "[1,"false",false]"
JSON.stringify()
Седьмая характеристика
Относительно перечислимости свойств объекта:
- Другие типы объектов, включая Map/Set/WeakMap/WeakSet, будут сериализовать только перечисляемые свойства.
// 不可枚举的属性默认会被忽略:
JSON.stringify(
Object.create(
null,
{
x: { value: 'json', enumerable: false },
y: { value: 'stringify', enumerable: true }
}
)
);
// "{"y":"stringify"}"
JSON.stringify()
Восьмая главная особенность
Все мы знаем, что самый простой и грубый способ реализации глубокого копирования — это сериализация:JSON.parse(JSON.stringify())
, реализация глубокого копирования таким образом приведет ко многим ямам из-за многих характеристик сериализации: таких как проблема циклических ссылок, о которой мы сейчас поговорим.
// 对包含循环引用的对象(对象之间相互引用,形成无限循环)执行此方法,会抛出错误。
const obj = {
name: "loopObj"
};
const loopObj = {
obj
};
// 对象之间形成循环引用,形成闭环
obj.loopObj = loopObj;
// 封装一个深拷贝的函数
function deepClone(obj) {
return JSON.parse(JSON.stringify(obj));
}
// 执行深拷贝,抛出错误
deepClone(obj)
/**
VM44:9 Uncaught TypeError: Converting circular structure to JSON
--> starting at object with constructor 'Object'
| property 'loopObj' -> object with constructor 'Object'
--- property 'obj' closes the circle
at JSON.stringify (<anonymous>)
at deepClone (<anonymous>:9:26)
at <anonymous>:11:13
*/
- Выполнение этого метода для объектов, содержащих циклические ссылки (объекты, ссылающиеся друг на друга, образующие бесконечный цикл), вызовет ошибку.
Вот почему, когда для реализации глубокого копирования используется сериализация, возникает ошибка при обнаружении объектов с циклическими ссылками.
JSON.stringify()
Девятая характеристика
Наконец, оsymbol
Есть еще одна вещь, которую нужно сказать о свойствах:
- все с
symbol
Атрибуты, являющиеся ключами атрибутов, полностью игнорируются, даже еслиreplacer
Параметры обязательны для их включения.
JSON.stringify({ [Symbol.for("json")]: "stringify" }, function(k, v) {
if (typeof k === "symbol") {
return v;
}
})
// undefined
replacer
даJSON.stringify()
Второй параметр , мы редко используем его, поэтому часто забываемJSON.stringify()
Второй и третий параметры, сцен не так много, но будет очень удобно, если правильно их использовать.JSON.stringify()
В примере с девятой характеристикойreplacer
Студенты, которые не понимают параметры, не беспокойтесь, на самом деле это очень просто, мы поймем это в следующем исследовании.
второй и третий параметры
мощный второй параметрreplacer
replacer
Параметр имеет две формы, это может быть функция или массив. При использовании в качестве функции имеет два параметра, ключ (ключ) и значение (значение), функция аналогична методу массива.map
,filter
Функция обратного вызова других методов, функция будет выполняться один раз для каждого значения атрибута. еслиreplacer
представляет собой массив, значения которого представляют имена свойств, которые будут сериализованы в строки JSON.
replacer
как функция
Может нарушить большинство из девяти характеристик
второй параметрreplacer
очень могущественный,replacer
В качестве функций мы можем разбить большинство из девяти фич, перейдем сразу к коду.
const data = {
a: "aaa",
b: undefined,
c: Symbol("dd"),
fn: function() {
return true;
}
};
// 不用 replacer 参数时
JSON.stringify(data);
// "{"a":"aaa"}"
// 使用 replacer 参数作为函数时
JSON.stringify(data, (key, value) => {
switch (true) {
case typeof value === "undefined":
return "undefined";
case typeof value === "symbol":
return value.toString();
case typeof value === "function":
return value.toString();
default:
break;
}
return value;
})
// "{"a":"aaa","b":"undefined","c":"Symbol(dd)","fn":"function() {\n return true;\n }"}"
Хотя использование метода toString() немного мошенническое, я должен сказать, что второй параметр очень мощный.
входящийreplacer
первый параметр функции
Следует отметить, что при передаче заменителя в функцию первым параметром является не первая пара ключ-значение объекта, а пустая строка в качестве значения ключа, а значением является пара ключ-значение объекта. весь объект:
const data = {
a: 2,
b: 3,
c: 4,
d: 5
};
JSON.stringify(data, (key, value) => {
console.log(value);
return value;
})
// 第一个被传入 replacer 函数的是 {"":{a: 2, b: 3, c: 4, d: 5}}
// {a: 2, b: 3, c: 4, d: 5}
// 2
// 3
// 4
// 5
выполнитьmap
функция
Мы также можем использовать его для реализации картографической функции объекта вручную.
// 实现一个 map 函数
const data = {
a: 2,
b: 3,
c: 4,
d: 5
};
const objMap = (obj, fn) => {
if (typeof fn !== "function") {
throw new TypeError(`${fn} is not a function !`);
}
return JSON.parse(JSON.stringify(obj, fn));
};
objMap(data, (key, value) => {
if (value % 2 === 0) {
return value / 2;
}
return value;
});
// {a: 1, b: 3, c: 2, d: 5}
replacer
как массив
replacer
В качестве массива результат очень прост: значение массива представляет собой имя свойства, которое будет сериализовано в строку JSON.
const jsonObj = {
name: "JSON.stringify",
params: "obj,replacer,space"
};
// 只保留 params 属性的值
JSON.stringify(jsonObj, ["params"]);
// "{"params":"obj,replacer,space"}"
Интересный, но бесполезный третий параметрspace
space
Параметры используются для управления интервалом в результирующей строке. Давайте сначала посмотрим на пример, чтобы увидеть, для чего используется эта штука:
const tiedan = {
name: "弹铁蛋同学",
describe: "今天在学 JSON.stringify()",
emotion: "like shit"
};
JSON.stringify(tiedan, null, "🐷");
// 接下来是输出结果
// "{
// 🐷"name": "弹铁蛋同学",
// 🐷"describe": "今天在学 JSON.stringify()",
// 🐷"emotion": "like shit"
// }"
JSON.stringify(tiedan, null, 2);
// "{
// "name": "弹铁蛋同学",
// "describe": "今天在学 JSON.stringify()",
// "emotion": "like shit"
// }"
В приведенном выше коде сразу видна роль третьего параметра, это прибамбасы, на самом деле этот параметр относительно безвкусен, и от него нет особой пользы, кроме красоты. мы используем\t
,\n
Равный отступ делает вывод более форматированным и удобным для просмотра.
-
Если это число, каждый уровень будет иметь отступ с большим количеством пробелов (до 10 пробелов), чем предыдущий уровень при строковом преобразовании;
-
Если это строка, то на каждом уровне отступ строки (или первых 10 символов строки) больше, чем на предыдущем уровне.
Суммировать
JSON.stringify()
Девять характеристик:
1. Дляundefined
, любую функцию иsymbol
Три специальных значения используются в качестве значения свойства объекта, элемента массива и возвращаемого результата отдельного значения.
-
undefined
, любую функцию иsymbol
как значение свойства объектаJSON.stringify()
пропустить (игнорировать) сериализацию их -
undefined
, любую функцию иsymbol
В качестве значения элемента массиваJSON.stringify()
будет сериализовать их какnull
-
undefined
, любую функцию иsymbol
одеялоJSON.stringify()
возвращается при сериализации как отдельное значениеundefined
Во-вторых, не гарантируется, что свойства объектов, не являющихся массивами, появятся в сериализованной строке в определенном порядке.
3. Если ценность конверсииtoJSON()
функция, какое значение возвращает функция, каково значение сериализованного результата, а значения других свойств игнорируются.
Четыре,JSON.stringify()
сериализуется нормальноDate
ценность .
Пятерки,NaN
а такжеInfinity
значение формата иnull
будет рассматриваться какnull
.
6. Упаковочные объекты логических значений, чисел и строк будут автоматически преобразованы в соответствующие примитивные значения в процессе сериализации.
7. Другие типы объектов, включая Map/Set/WeakMap/WeakSet, сериализуют только перечисляемые свойства.
8. Выполнение этого метода для объектов, содержащих циклические ссылки (объекты ссылаются друг на друга, образуя бесконечный цикл), вызовет ошибку.
Девять, всеsymbol
Атрибуты, являющиеся ключами атрибутов, полностью игнорируются, даже еслиreplacer
Параметры обязательны для их включения.
JSON.stringify()
второй и третий параметры
Мощный второй параметр:
- При использовании в качестве функции имеет два параметра, ключ (ключ) и значение (значение), функция аналогична методу массива.
map
,filter
Функция обратного вызова других методов, функция будет выполняться один раз для каждого значения атрибута (в этот период мы также просто реализовалиmap
функция). - если
replacer
представляет собой массив, значения которого представляют имена свойств, которые будут сериализованы в строки JSON.
Шикарный третий параметр:
-
Если это число, каждый уровень будет иметь отступ с большим количеством пробелов (до 10 пробелов), чем предыдущий уровень при строковом преобразовании;
-
Если это строка, то на каждом уровне отступ строки (или первых 10 символов строки) больше, чем на предыдущем уровне.
Уведомление:
В третьем плане первого примера маленький партнер предположил, что этот план будет рискованным, что действительно так (Может заменить стоимость объекта). Пожалуйста, используйте его с осторожностью, в большинстве случаев это нормально. Четвертое решение, предоставленное друзьями, все еще очень хорошее:
const todayILearn = {
_id: 1,
content: '今天学习 JSON.stringify(),我很开心!',
created_at: 'Mon Nov 25 2019 14:03:55 GMT+0800 (中国标准时间)',
updated_at: 'Mon Nov 25 2019 16:03:55 GMT+0800 (中国标准时间)'
}
const mapObj = {
_id: "id",
created_at: "createdAt",
updated_at: "updatedAt"
};
Object.fromEntries(Object.entries(todayILearn).map(([k, v]) => [mapObj[k]||k, v]))
// {
// id: 1,
// content: '今天学习 JSON.stringify(),我很开心!',
// createdAt: 'Mon Nov 25 2019 14:03:55 GMT+0800 (中国标准时间)',
// updatedAt: 'Mon Nov 25 2019 16:03:55 GMT+0800 (中国标准时间)'
// }
Рекомендуемое чтение
Интервьюер спросил серию вопросов: выравнивание массива (выравнивание) реализация плоского метода