JSON.stringify
est une méthode souvent utilisée dans le développement quotidien. Pouvez-vous vraiment l'utiliser de manière flexible ?
Avant d'étudier cet article, Xiaobao souhaite que tout le monde réponde à quelques questions et apprenne stringify
en profondeur.
stringify
a plusieurs paramètres.Quelle est l'utilité de chaque paramètre ?stringify
? null、undefined、NaN
seront-ellesES6
Y aura-t-il un traitement spécial pendant le processus de sérialisation du type Symbol
et BigInt
?stringify
n'est - il pas adapté à la copie profonde ?stringify
?Le contexte de l'article entier est cohérent avec la carte mentale ci - dessous. peut laisser une impression en premier.
Dans la programmation quotidienne, nous utilisons souvent la méthode JSON.stringify
pour convertir un objet en forme de chaîne JSON
.
const stu = { nom : 'zcxiaobao', âge : 18 ans } // {"nom": "zcxiaobao", "âge": 18} console.log(JSON.stringify(stu));
Mais est-ce que stringify
est vraiment aussi simple ? Jetons d'abord un coup d'œil à la définition de stringify
dans MDN
.
MDN indique : La méthode JSON.stringify()
convertit un objet ou une valeur JavaScript
en chaîne JSON
. Si une fonction replacer
est spécifiée, la valeur peut éventuellement être remplacée, ou le replacer
spécifié est un tableau. Contient les propriétés spécifiées par le tableau. .
Après avoir lu la définition, Xiaobao a été surpris. stringfy
a-t-il plus d'un paramètre ? Bien entendu, stringify
a trois paramètres.
Jetons un coup d'œil à la syntaxe stringify
et à l'introduction des paramètres :
JSON.stringify(value[, replacer [, space]])
value
: La valeur à séquencer dans une chaîne JSON.replacer
(facultatif) Si le paramètre est une fonction , lors du processus de sérialisation, chaque attribut de la valeur sérialisée sera converti et traité par la fonction ;
si le paramètre est un tableau , seules les propriétés contenues dans ce tableau seront Uniquement l'attribut ; les noms seront sérialisés dans la chaîne JSON
finale.
Si ce paramètre est null
ou non fourni, tous les attributs de l'objet seront sérialisés.
space
(facultatif) : Spécifie la chaîne d'espaces utilisée pour l'indentation, utilisée pour embellir la sortie. Si le paramètre est un nombre, il représente le nombre d'espaces. La limite supérieure est de 10.
Si la valeur est inférieure à 1, cela signifie qu'il n'y a pas d'espaces.
Si
le paramètre est une chaîne (lorsque la longueur de la chaîne dépasse 10 lettres, les 10 premières lettres sont prises), la chaîne sera traitée comme des espaces.
le paramètre n'est pas fourni (ou est nul), il n'y aura pas d'espaces
replacer
replacer
en tant que fonction
replacer
en tant que fonction, il a deux paramètres, key ( key
) et value ( value
), et les deux paramètres seront sérialisés.
Au début, la fonction de remplacement sera passée dans une chaîne vide comme valeur clé, représentant l'objet à chaîner . Il est important de comprendre cela. La fonction replacer
n'analyse pas l'objet en paires clé-valeur lorsqu'il apparaît, mais transmet d'abord l'objet à sérialiser . Ensuite, les propriétés de chaque objet ou tableau sont transmises séquentiellement. Si la valeur de retour de la fonction est indéfinie ou fonction, la valeur de l'attribut sera filtrée et le reste suivra les règles de retour.
// le repalcer accepte la valeur clé de deux paramètres // La valeur clé est chaque paire clé-valeur de l'objet // nous pouvons donc simplement filtrer en fonction du type de clé ou de valeur function replacer(key, value) { if (type de valeur === "string") { retourner indéfini ; } valeur de retour ; } // la fonction peut tester la fonction par elle-même replacerFunc(key, value) { if (type de valeur === "string") { retourner () => {} ; } valeur de retour ; } const foo = {fondation : "Mozilla", modèle : "box", semaine : 45, transport : "voiture", mois : 7} ; const jsonString = JSON.stringify(foo, replacer);
JSON
est {"week":45,"month":7}
mais si la sérialisation est un tableau, si replacer
renvoie undefined
ou une fonction, la valeur actuelle ne sera pas ignoré et sera remplacé par null
.
liste const = [1, '22', 3] const jsonString = JSON.stringify(list, replacer)Le résultat de la sérialisation JSON est
replacer
JSON
[1,null,3]'
est plus facile à comprendre sous forme de tableau, filtrant les valeurs clés apparaissant dans le tableau.
const foo = {fondation : "Mozilla", modèle : "box", semaine : 45, transport : "voiture", mois : 7} ; const jsonString = JSON.stringify(foo, ['week', 'month']);
Le résultat de la sérialisation JSON est {"week":45,"month":7}
, et seules week
et month
sont retenu.
apparaissant dans les valeurs d'attribut d'objet non-tableau : undefined
, toute fonction et les valeurs Symbol
seront ignorées pendant le processus de sérialisation.
Apparaissant dans les tableaux : undefined
, toute fonction, et les valeurs Symbol
seront ignorées. Lorsqu'elles sont converties en null
seules : undefined sera renvoyé
// 1. L'existence de ces trois valeursdans la valeur de l'attribut de l'objet sera ignorée const obj = { nom : 'zc', âge : 18 ans, // La fonction sera ignorée sayHello() { console.log('bonjour tout le monde') }, // non défini sera ignoré épouse : non définie, // La valeur du symbole sera ignorée id : Symbol(111), // [Symbole('zc')] : 'zc', } // Résultat de sortie : {"name": "zc", "age": 18} console.log(JSON.stringify(obj)); // 2. Ces trois valeurs du tableau seront converties en null liste const = [ 'zc', 18, // Fonction convertie en null fonction direBonjour() { console.log('bonjour tout le monde') }, // non défini converti en null indéfini, // Symbole converti en null Symbole(111) ] // ["zc",18, nul, nul, nul] console.log(JSON.stringify(liste)) // 3. La conversion séparée de ces trois valeurs renverra un élément indéfini console.log(JSON.stringify(undefined)) // non défini console.log(JSON.stringify(Symbol(111))) // non défini console.log(JSON.stringify(function sayHello() { console.log('bonjour tout le monde') })) //
convertit la valeur S'il existe toJSON()
, quelle que soit la valeur renvoyée toJSON()
elle sera la valeur renvoyée par le résultat de la sérialisation, et les autres valeurs le seront. ignoré.
const obj = { nom : 'zc', versJSON(){ return 'revenir à JSON' } } // retourne à JSON console.log(JSON.stringify(obj));
les valeurs booléennes, les nombres et les chaînes seront automatiquement convertis en la valeur d'origine JSON correspondante pendant le processus de sérialisation.
. stringify([new Number(1), new String("zcxiaobao"), new Boolean(true)]); // [1,"zcxiaobao",true]
La fonctionnalité quatre est principalement destinée aux valeurs spéciales en JavaScript
, telles que NaN
, Infinity
et null dans le type Number
. Ces trois types de valeurs seront traités comme null
lors de la sérialisation .
// [nul, nul, nul, nul, nul] JSON.stringify([null, NaN, -NaN, Infinity, -Infinity]) // La fonctionnalité 3 mentionne que les objets d'empaquetage de valeurs booléennes, de nombres et de chaînes seront automatiquement convertis en valeurs originales correspondantes pendant le processus de sérialisation // La conversion de type implicite appellera la classe d'empaquetage, donc Number => NaN sera appelé en premier // Puis convertissez en null // 1/0 => Infini => nul JSON.stringify([Number('123a'), +'123a', 1/0])
La méthode toJSON
(identique à Date.toISOString()
) est déployée sur l'objet Date
pour le convertir en chaîne, donc JSON.stringify() sérialisera la valeur Date dans une chaîne de format d'heure .
// "2022-03-06T08:24:56.138Z" JSON.stringify(new Date())
lors de la mention de la fonctionnalité Symbol, lorsque Symbol
est utilisé comme valeur, les objets, les tableaux et les utilisations individuelles seront ignorés, convertis en null
et convertis en undefined
respectivement.
De même, toutes les propriétés avec Symbol comme clé de propriété seront complètement ignorées, même si elles doivent être incluses de force dans le paramètre de remplacement .
const obj = { nom : 'zcxiaobao', âge : 18 ans, [Symbole('lyl')] : 'unique' } remplacement de fonction (clé, valeur) { if (type de clé === 'symbole') { valeur de retour ; } } // non défini JSON.stringify(obj, replacer);
À partir du cas ci-dessus, nous pouvons voir que même si nous spécifions de force la valeur du type Symbol
de retour via replacer
, elle finira par être ignorée.
JSON.stringify
stipule : Essayer de convertir une valeur de type BigInt
générera TypeError
const bigNumber = BigInt(1) // Uncaught TypeError : je ne sais pas comment sérialiser un BigInt Console.log(JSON.stringify(bigNumber))
La fonctionnalité 8 souligne : L'exécution de cette méthode sur des objets contenant des références circulaires (les objets se réfèrent les uns aux autres, formant une boucle infinie) générera une erreur
Daily Development Deep Copy
.Le moyen le plus simple et le plus violent consiste à utiliser JSON.parse(JSON.stringify(obj))
, mais la copie complète sous cette méthode présente d'énormes pièges. Le problème clé est que stringify
ne peut pas gérer le problème de référence circulaire.
const obj = { nom : 'zcxiaobao', âge : 18 ans, } const boucleObj = { obj } // Former une référence circulaire obj.loopObj = loopObj; JSON.stringify(obj) /* Uncaught TypeError : Conversion d'une structure circulaire en JSON -> en commençant par l'objet avec le constructeur 'Object' | propriété 'loopObj' -> objet avec le constructeur 'Object' --- la propriété 'obj' ferme le cercle sur JSON.stringify (<anonyme>) à <anonyme> :10:6 */
la sérialisation des propriétés énumérables des objets (y compris Map/Set/WeakMap/WeakSet
), en plus de certaines des situations mentionnées ci-dessus, stringify
stipule également clairement que seules les propriétés énumérables seront sérialisées
// Non énumérable les propriétés seront ignorées par défaut // {"age":18} JSON.stringify( Objet.create( nul, { nom : { valeur : 'zcxiaobao', énumérable : false }, âge : { valeur : 18, énumérable : vrai } } ) );
L'objet localStorage
est utilisé pour sauvegarder les données de l'ensemble du site Web pendant une longue période. Les données enregistrées n'ont pas de délai d'expiration jusqu'à ce qu'elles soient supprimées manuellement. Habituellement, nous le stockons sous forme d’objets.
Appelez simplement la méthode objet localStorage
const obj = { nom : 'zcxiaobao', âge : 18 ans } // Appelez simplement localStorage.setItem() localStorage.setItem('zc', obj); //Le résultat final renvoyé est [object Object] // On peut voir que le simple appel de localStorage échoue console.log(localStorage.getItem('zc'))
localStorage
coopère avec JSON.stringify
localStorage.setItem('zc', JSON.stringify(obj)); //Le résultat final renvoyé est {nom : 'zcxiaobao', âge : 18} Console.log(JSON.parse(localStorage.getItem('zc')))
suppose un tel scénario. Le backend renvoie un objet long avec de nombreux attributs, et nous n'en avons besoin que de quelques-uns et nous devons les stocker. attributs dans localStorage
.
Option 1 : Affectation de déstructuration + stringify
// Nous n'avons besoin que des attributs a, e, f const obj = { a:1, b:2, c:3, d:4, e:5, f:6, g:7 } // Affectation de déstructuration const {a,e,f} = obj; // Stocker dans localStorage localStorage.setItem('zc', JSON.stringify({a,e,f})) // {"a":1,"e":5,"f":6} console.log(localStorage.getItem('zc'))
utilise le paramètre replacer
de stringify
// Utiliser le remplacement pour filtrer sous forme de tableau localStorage.setItem('zc', JSON.stringify(obj, ['a','e' , 'f'])) // {"a":1,"e":5,"f":6} console.log(localStorage.getItem('zc'))
Lorsque replacer
est un tableau, nous pouvons simplement filtrer les attributs dont nous avons besoin, ce qui est une bonne petite astuce.
L'utilisation de JSON.parse(JSON.stringify)
est l'un des moyens les plus simples et les plus violents d'implémenter des copies complètes d'objets. Mais comme le titre l’indique, l’utilisation de cette méthode de copie approfondie nécessite une réflexion approfondie.
Problème de référence circulaire, stringify
signalera
la fonction d'erreur, undefined
, Symbol
sera ignoré,
NaN
, Infinity
et -Infinity
seront sérialisés en null
...
Par conséquent, lorsque vous utilisez JSON.parse(JSON.stringify)
pour effectuer une copie approfondie, vous devez réfléchissez bien. S'il n'y a pas de dangers cachés mentionnés ci-dessus, JSON.parse(JSON.stringify)
est une solution de copie approfondie réalisable.
Lors de la programmation avec des tableaux, on utilise souvent la fonction map
. Avec le paramètre replacer
, nous pouvons utiliser ce paramètre pour implémenter la fonction map
de l'objet.
const ObjectMap = (obj, fn) => { if (typeof fn !== "function") { throw new TypeError(`${fn} n'est pas une fonction !`); } // Appelez d'abord JSON.stringify(obj, replacer) pour implémenter la fonction map // Appelez ensuite JSON.parse pour le reconvertir en objet return JSON.parse(JSON.stringify(obj, fn)); } ; // Par exemple, ce qui suit multiplie la valeur d'attribut de l'objet obj par 2 const obj = { une: 1, b: 2, c : 3 } console.log(ObjectMap(obj, (key, val) => { if (type de valeur === "nombre") { valeur de retour * 2 ; } valeur de retour ; }))
De nombreux étudiants se demandent peut-être pourquoi un jugement supplémentaire est requis. N'est-il pas possible de simplement return value * 2
?
Comme mentionné ci-dessus, replacer
passe d'abord dans l'objet à sérialiser. L'objet * 2 => NaN => toJSON(NaN) => undefined => est ignoré et il n'y aura pas d'analyse ultérieure de la paire clé-valeur.
Avec la fonction replacer
, on peut également supprimer certains attributs de l'objet.
const obj = { nom : 'zcxiaobao', âge : 18 ans } // {"âge":18} JSON.stringify(obj, (clé, val) => { // Lorsque la valeur de retour n'est pas définie, cette propriété sera ignorée if (key === 'name') { retourner indéfini ; } valeur de retour ; })
JSON.stringify
peut sérialiser des objets en chaînes, nous pouvons donc utiliser des méthodes de chaîne pour implémenter des jugements simples d'égalité d'objet.
// Détermine si le tableau contient un objet const noms = [ {nom : 'zcxiaobao'}, {nom :'txtx'}, {nom : 'mymy'}, ]; const zcxiaobao = {nom : 'zcxiaobao'} ; // vrai JSON.stringify(noms).includes(JSON.stringify(zcxiaobao)) // Détermine si les objets sont égaux const d1 = {type: 'div'} const d2 = {type : 'div'} // vrai JSON.stringify(d1) === JSON.stringify(d2);
Avec l'aide des idées ci-dessus, nous pouvons également réaliser une déduplication simple d'objets de tableau.
Mais comme les résultats de la sérialisation JSON.stringify
{x:1, y:1}
et {y:1, x:1}
sont différents, nous devons traiter les objets du tableau avant de commencer.
Méthode 1 : Organisez les clés de chaque objet dans le tableau dans l'ordre du dictionnaire
arr.forEach(item => { const nouvelÉlément = {} ; Object.keys(item) // Récupère la clé de l'objet value.sort() // Valeur de la clé sorting.map(key => { // Génère un nouvel objet newItem[key] = item[key]; }) // Utilisez newItem pour effectuer l'opération de déduplication})
Mais la première méthode est un peu lourde. JSON.stringify
fournit replacer
, qui peut filtrer le tableau.
Méthode 2 : replacer
la fonction de format de tableau de remplacement unique(arr) { const keySet = new Set(); const uniqueObj = {} // Extrait toutes les clés arr.forEach(item => { Object.keys(item).forEach(key => keySet.add(key)) }) const remplaçant = [...keySet]; arr.forEach(article => { // Tous les objets sont filtrés en fonction du remplacement de valeur de clé spécifié unique[JSON.stringify(item, replacer)] = item; }) retourner Object.keys(unique).map(u => JSON.parse(u)) } //Test unique([{}, {}, {x:1}, {x:1}, {a:1}, {x:1,a:1}, {x:1,a:1}, {x:1,a:1,b:1} ]) // Renvoie le résultat [{},{"x":1},{"a":1},{"x":1,"a":1},{"x":1,"a":1 ,"b":1}]