JSON.stringify を理解し、その使用方法を確認します。
強力な JSON.stringify メソッドの使用方法を本当に知っていますか?以下の記事でJSON.stringifyの詳しい理解と使い方を紹介していますので、お役に立てれば幸いです。
JSON.stringify
日々の開発でよく使われる手法ですが、本当に柔軟に使えるのでしょうか?
この記事を学ぶ前に、Xiaobao は皆さんにいくつかの質問を受けて、stringify
について詳しく一緒に学んでほしいと考えています。 [関連する推奨事項: javascript ビデオ チュートリアル ]
-
stringify
関数には複数のパラメータがあります。各パラメータの用途は何ですか? -
stringify
シリアル化のガイドラインとは何ですか?- 関数のシリアル化をどのように扱うか?
-
null、未定義、NaN
およびその他の特殊な値 -
ES6
後で追加されたSymbol
型とBigInt
はシリアル化プロセス中に特別に扱われますか?
-
stringify
なぜディープ コピーに適していないのですか? -
stringify
?
記事全体の文脈は以下のマインド マップと一致しています。最初に印象を残してください。
3 つのパラメータ
日常のプログラミングでは、JSON.stringify
メソッドを使用して、 object JSON
文字列形式に変換します。
const stu = { name: 'zcxiaobao', age: 18 } // {"name":"zcxiaobao","age":18} console.log(JSON.stringify(stu));
でも stringify
本当にそんなに簡単なのでしょうか?まず、MDN
の stringify
の定義を見てみましょう。
MDN の内容: JSON.stringify()
メソッドは、JavaScript
オブジェクトまたは値を JSON
文字に変換します。 replacer
関数が指定されている場合は文字列で、オプションで値を置換します。または、指定された replacer
が配列の場合は、オプションで配列で指定されたプロパティのみを含めます。
定義を読んだ後、Xiaabao は驚きました。stringfy
パラメータは複数あるのですか?もちろん、stringify
には 3 つのパラメータがあります。
stringify
構文とパラメーターの概要を見てみましょう:
JSON.stringify(value[, replacer [, space]])
value
: JSON 文字列にシーケンス化される値。replacer
(オプション)パラメータが function の場合、シリアル化プロセス中に、値のシリアル化された Each 属性がこの関数によって変換および処理されます。
パラメータが array の場合、この配列に含まれる属性名のみが最終的な配列にシリアル化されます。
JSON
stringこのパラメータが
null
であるか指定されていない場合、オブジェクトのすべてのプロパティはシリアル化されます。
space
(オプション): インデントに使用される空白文字列を指定します。出力を美しくするために使用されます。パラメータはスペースの数を表す数値です。上限は 10 です。- 値が 1 未満の場合は、スペースがないことを意味します。
- パラメータが文字列の場合 (文字列の長さが を超える場合) 10 文字 (最初の 10 文字)、文字列はスペースとして扱われます。
# このパラメータが指定されていない場合 (または null の場合)、スペースはありません
replacer を使用してみましょう。
- 関数として
replacer 関数として、これには 2 つのパラメーターがあります。キー (
) と値 (value
)、および両方のパラメーターはシリアル化されます。 最初に、
replacer 関数は、文字列化されるオブジェクト
を表す空の文字列でキー値として渡されます。これを理解することが重要です。
関数は、オブジェクトの起動時にオブジェクトをキーと値のペアに解析せず、シリアル化する オブジェクトを最初に渡します。次に、各オブジェクトまたは配列のプロパティが順番に渡されます。 関数の戻り値が未定義または関数の場合、属性値はフィルターで除外されます、残りは戻り規則に従います。
// repalcer 接受两个参数 key value // key value 分别为对象的每个键值对 // 因此我们可以根据键或者值的类型进行简单筛选 function replacer(key, value) { if (typeof value === "string") { return undefined; } return value; } // function 可自己测试 function replacerFunc(key, value) { if (typeof value === "string") { return () => {}; } return value; } const foo = {foundation: "Mozilla", model: "box", week: 45, transport: "car", month: 7}; const jsonString = JSON.stringify(foo, replacer);
ただし、シリアル化が配列の場合、
replacer 関数が
unknown
null に置き換えられます。
const list = [1, '22', 3] const jsonString = JSON.stringify(list, replacer)
JSON シリアル化された結果は '[1,null,3]'です
#replacer
配列として
配列として表すと分かりやすく、配列内に出現するキー値をフィルタリングします。
<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class='brush:php;toolbar:false;'>const foo = {foundation: "Mozilla", model: "box", week: 45, transport: "car", month: 7}; const jsonString = JSON.stringify(foo, [&#39;week&#39;, &#39;month&#39;]);</pre><div class="contentsignin">ログイン後にコピー</div></div><p>JSON 序列化结果为 <code>{"week":45,"month":7}
, 只保留week
和month
属性值。九特性
特性一: undefined、函数、Symbol值
出现在非数组对象属性值中:
undefined
、任意函数、Symbol
值在序列化过程中将会被忽略出现在数组中:
undefined
、任意函数、Symbol
值会被转化为 null单独转换时: 会返回 undefined
// 1. 对象属性值中存在这三种值会被忽略 const obj = { name: 'zc', age: 18, // 函数会被忽略 sayHello() { console.log('hello world') }, // undefined会被忽略 wife: undefined, // Symbol值会被忽略 id: Symbol(111), // [Symbol('zc')]: 'zc', } // 输出结果: {"name":"zc","age":18} console.log(JSON.stringify(obj)); // 2. 数组中这三种值会被转化为 null const list = [ 'zc', 18, // 函数转化为 null function sayHello() { console.log('hello world') }, // undefined 转换为 null undefined, // Symbol 转换为 null Symbol(111) ] // ["zc",18,null,null,null] console.log(JSON.stringify(list)) // 3. 这三种值单独转化将会返回 undefined console.log(JSON.stringify(undefined)) // undefined console.log(JSON.stringify(Symbol(111))) // undefined console.log(JSON.stringify(function sayHello() { console.log('hello world') })) // undefined
ログイン後にコピー特性二: toJSON() 方法
转换值如果有
toJSON()
方法,toJSON()
方法返回什么值,序列化结果就返回什么值,其余值会被忽略。const obj = { name: 'zc', toJSON(){ return 'return toJSON' } } // return toJSON console.log(JSON.stringify(obj));
ログイン後にコピー特性三: 布尔值、数字、字符串的包装对象
布尔值、数字、字符串的包装对象在序列化过程中会自动转换成对应的原始值
JSON.stringify([new Number(1), new String("zcxiaobao"), new Boolean(true)]); // [1,"zcxiaobao",true]
ログイン後にコピー特性四: NaN Infinity null
特性四主要针对
JavaScript
里面的特殊值,例如Number
类型里的NaN
和Infinity
及 null 。此三种数值序列化过程中都会被当做null
。// [null,null,null,null,null] JSON.stringify([null, NaN, -NaN, Infinity, -Infinity]) // 特性三讲过布尔值、数字、字符串的包装对象在序列化过程中会自动转换成对应的原始值 // 隐式类型转换就会调用包装类,因此会先调用 Number => NaN // 之后再转化为 null // 1/0 => Infinity => null JSON.stringify([Number('123a'), +'123a', 1/0])
ログイン後にコピー特性五: Date对象
Date
对象上部署了toJSON
方法(同Date.toISOString()
)将其转换为字符串,因此 JSON.stringify() 将会序列化 Date 的值为时间格式字符串。// "2022-03-06T08:24:56.138Z" JSON.stringify(new Date())
ログイン後にコピー特性六: Symbol
特性一提到,
Symbol
类型当作值来使用时,对象、数组、单独使用分别会被忽略、转换为null
、转化为undefined
。同样的,所有以 Symbol 为属性键的属性都会被完全忽略掉,即便 replacer 参数中强制指定包含了它们。
const obj = { name: 'zcxiaobao', age: 18, [Symbol('lyl')]: 'unique' } function replacer(key, value) { if (typeof key === 'symbol') { return value; } } // undefined JSON.stringify(obj, replacer);
ログイン後にコピー通过上面案例,我们可以看出,虽然我们通过
replacer
强行指定了返回Symbol
类型值,但最终还是会被忽略掉。特性七: BigInt
JSON.stringify
规定: 尝试去转换BigInt
类型的值会抛出TypeError
const bigNumber = BigInt(1) // Uncaught TypeError: Do not know how to serialize a BigInt console.log(JSON.stringify(bigNumber))
ログイン後にコピー特性八: 循环引用
特性八指出: 对包含循环引用的对象(对象之间相互引用,形成无限循环)执行此方法,会抛出错误
日常开发中深拷贝最简单暴力的方式就是使用
JSON.parse(JSON.stringify(obj))
,但此方法下的深拷贝存在巨坑,关键问题就在于stringify
无法处理循环引用问题。const obj = { name: 'zcxiaobao', age: 18, } const loopObj = { obj } // 形成循环引用 obj.loopObj = loopObj; JSON.stringify(obj) /* 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 <anonymous>:10:6 */
ログイン後にコピー特性九: 可枚举属性
对于对象(包括
Map/Set/WeakMap/WeakSet
)的序列化,除了上文讲到的一些情况,stringify
也明确规定,仅会序列化可枚举的属性// 不可枚举的属性默认会被忽略 // {"age":18} JSON.stringify( Object.create( null, { name: { value: 'zcxiaobao', enumerable: false }, age: { value: 18, enumerable: true } } ) );
ログイン後にコピー六妙用
localStorage
localStorage
对象用于长久保存整个网站的数据,保存的数据没有过期时间,直到手动去删除。通常我们以对象形式进行存储。单纯调用
localStorage
对象方法
const obj = { name: 'zcxiaobao', age: 18 } // 单纯调用 localStorage.setItem() localStorage.setItem('zc', obj); // 最终返回结果是 [object Object] // 可见单纯调用localStorage是失败的 console.log(localStorage.getItem('zc'))
ログイン後にコピーlocalStorage
配合JSON.stringify
方法
localStorage.setItem('zc', JSON.stringify(obj)); // 最终返回结果是 {name: 'zcxiaobao', age: 18} console.log(JSON.parse(localStorage.getItem('zc')))
ログイン後にコピー属性过滤
来假设这样一个场景,后端返回了一个很长的对象,对象里面属性很多,而我们只需要其中几个属性,并且这几个属性我们要存储到
localStorage
中。方案一: 解构赋值+
stringify
// 我们只需要 a,e,f 属性 const obj = { a:1, b:2, c:3, d:4, e:5, f:6, g:7 } // 解构赋值 const {a,e,f} = obj; // 存储到localStorage localStorage.setItem('zc', JSON.stringify({a,e,f})) // {"a":1,"e":5,"f":6} console.log(localStorage.getItem('zc'))
ログイン後にコピー使用
stringify
的replacer
参数
// 借助 replacer 作为数组形式进行过滤 localStorage.setItem('zc', JSON.stringify(obj, ['a','e','f'])) // {"a":1,"e":5,"f":6} console.log(localStorage.getItem('zc'))
ログイン後にコピー当
replacer
是数组时,可以简单的过滤出我们所需的属性,是一个不错的小技巧。三思而后行之深拷贝
使用
JSON.parse(JSON.stringify)
是实现对象的深拷贝最简单暴力的方法之一。但也正如标题所言,使用该种方法的深拷贝要深思熟虑。循环引用问题,
stringify
会报错函数、
undefined
、Symbol
会被忽略NaN
、Infinity
和-Infinity
会被序列化成null
...
因此在使用
JSON.parse(JSON.stringify)
做深拷贝时,一定要深思熟虑。如果没有上述隐患,JSON.parse(JSON.stringify)
是一个可行的深拷贝方案。对象的 map 函数
在使用数组进行编程时,我们会经常使用到
map
函数。有了replacer
参数后,我们就可以借助此参数,实现对象的map
函数。const ObjectMap = (obj, fn) => { if (typeof fn !== "function") { throw new TypeError(`${fn} is not a function !`); } // 先调用 JSON.stringify(obj, replacer) 实现 map 功能 // 然后调用 JSON.parse 重新转化成对象 return JSON.parse(JSON.stringify(obj, fn)); }; // 例如下面给 obj 对象的属性值乘以2 const obj = { a: 1, b: 2, c: 3 } console.log(ObjectMap(obj, (key, val) => { if (typeof value === "number") { return value * 2; } return value; }))
ログイン後にコピー很多同学有可能会很奇怪,为什么里面还需要多加一部判断,直接
return value * 2
不可吗?上文讲过,
replacer
函数首先传入的是待序列化对象,对象 * 2 => NaN => toJSON(NaN) => undefined => 被忽略,就没有后续的键值对解析了。删除对象属性
借助
replacer
函数,我们还可以删除对象的某些属性。const obj = { name: 'zcxiaobao', age: 18 } // {"age":18} JSON.stringify(obj, (key, val) => { // 返回值为 undefined时,该属性会被忽略 if (key === 'name') { return undefined; } return val; })
ログイン後にコピー对象判断
JSON.stringify
可以将对象序列化为字符串,因此我们可以借助字符串的方法来实现简单的对象相等判断。//判断数组是否包含某对象 const names = [ {name:'zcxiaobao'}, {name:'txtx'}, {name:'mymy'}, ]; const zcxiaobao = {name:'zcxiaobao'}; // true JSON.stringify(names).includes(JSON.stringify(zcxiaobao)) // 判断对象是否相等 const d1 = {type: 'div'} const d2 = {type: 'div'} // true JSON.stringify(d1) === JSON.stringify(d2);
ログイン後にコピー数组对象去重
借助上面的思想,我们还能实现简单的数组对象去重。
但由于
JSON.stringify
序列化{x:1, y:1}
和{y:1, x:1}
结果不同,因此在开始之前我们需要处理一下数组中的对象。方法一: 将数组中的每个对象的键按字典序排列
arr.forEach(item => { const newItem = {}; Object.keys(item) // 获取对象键值 .sort() // 键值排序 .map(key => { // 生成新对象 newItem[key] = item[key]; }) // 使用 newItem 进行去重操作 })
ログイン後にコピー但方法一有些繁琐,
JSON.stringify
提供了replacer
数组格式参数,可以过滤数组。方法二: 借助
replacer
数组格式
function unique(arr) { const keySet = new Set(); const uniqueObj = {} // 提取所有的键 arr.forEach(item => { Object.keys(item).forEach(key => keySet.add(key)) }) const replacer = [...keySet]; arr.forEach(item => { // 所有的对象按照规定键值 replacer 过滤 unique[JSON.stringify(item, replacer)] = item; }) return Object.keys(unique).map(u => JSON.parse(u)) } // 测试一下 unique([{}, {}, {x:1}, {x:1}, {a:1}, {x:1,a:1}, {x:1,a:1}, {x:1,a:1,b:1} ]) // 返回结果 [{},{"x":1},{"a":1},{"x":1,"a":1},{"x":1,"a":1,"b":1}]
ログイン後にコピー【相关推荐:web前端】
以上がJSON.stringify を理解し、その使用方法を確認します。の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

AI Hentai Generator
AIヘンタイを無料で生成します。

人気の記事

ホットツール

メモ帳++7.3.1
使いやすく無料のコードエディター

SublimeText3 中国語版
中国語版、とても使いやすい

ゼンドスタジオ 13.0.1
強力な PHP 統合開発環境

ドリームウィーバー CS6
ビジュアル Web 開発ツール

SublimeText3 Mac版
神レベルのコード編集ソフト(SublimeText3)

ホットトピック









WebSocket と JavaScript を使用してオンライン音声認識システムを実装する方法 はじめに: 技術の継続的な発展により、音声認識技術は人工知能の分野の重要な部分になりました。 WebSocket と JavaScript をベースとしたオンライン音声認識システムは、低遅延、リアルタイム、クロスプラットフォームという特徴があり、広く使用されるソリューションとなっています。この記事では、WebSocket と JavaScript を使用してオンライン音声認識システムを実装する方法を紹介します。

WebSocketとJavaScript:リアルタイム監視システムを実現するためのキーテクノロジー はじめに: インターネット技術の急速な発展に伴い、リアルタイム監視システムは様々な分野で広く利用されています。リアルタイム監視を実現するための重要なテクノロジーの 1 つは、WebSocket と JavaScript の組み合わせです。この記事では、リアルタイム監視システムにおける WebSocket と JavaScript のアプリケーションを紹介し、コード例を示し、その実装原理を詳しく説明します。 1.WebSocketテクノロジー

JavaScript と WebSocket を使用してリアルタイム オンライン注文システムを実装する方法の紹介: インターネットの普及とテクノロジーの進歩に伴い、ますます多くのレストランがオンライン注文サービスを提供し始めています。リアルタイムのオンライン注文システムを実装するには、JavaScript と WebSocket テクノロジを使用できます。 WebSocket は、TCP プロトコルをベースとした全二重通信プロトコルで、クライアントとサーバー間のリアルタイム双方向通信を実現します。リアルタイムオンラインオーダーシステムにおいて、ユーザーが料理を選択して注文するとき

WebSocket と JavaScript を使用してオンライン予約システムを実装する方法 今日のデジタル時代では、ますます多くの企業やサービスがオンライン予約機能を提供する必要があります。効率的かつリアルタイムのオンライン予約システムを実装することが重要です。この記事では、WebSocket と JavaScript を使用してオンライン予約システムを実装する方法と、具体的なコード例を紹介します。 1. WebSocket とは何ですか? WebSocket は、単一の TCP 接続における全二重方式です。

JavaScript と WebSocket: 効率的なリアルタイム天気予報システムの構築 はじめに: 今日、天気予報の精度は日常生活と意思決定にとって非常に重要です。テクノロジーの発展に伴い、リアルタイムで気象データを取得することで、より正確で信頼性の高い天気予報を提供できるようになりました。この記事では、JavaScript と WebSocket テクノロジを使用して効率的なリアルタイム天気予報システムを構築する方法を学びます。この記事では、具体的なコード例を通じて実装プロセスを説明します。私たちは

JavaScript チュートリアル: HTTP ステータス コードを取得する方法、特定のコード例が必要です 序文: Web 開発では、サーバーとのデータ対話が頻繁に発生します。サーバーと通信するとき、多くの場合、返された HTTP ステータス コードを取得して操作が成功したかどうかを判断し、さまざまなステータス コードに基づいて対応する処理を実行する必要があります。この記事では、JavaScript を使用して HTTP ステータス コードを取得する方法を説明し、いくつかの実用的なコード例を示します。 XMLHttpRequestの使用

使用法: JavaScript では、insertBefore() メソッドを使用して、DOM ツリーに新しいノードを挿入します。このメソッドには、挿入される新しいノードと参照ノード (つまり、新しいノードが挿入されるノード) の 2 つのパラメータが必要です。

JavaScript で HTTP ステータス コードを取得する方法の紹介: フロントエンド開発では、バックエンド インターフェイスとの対話を処理する必要があることが多く、HTTP ステータス コードはその非常に重要な部分です。 HTTP ステータス コードを理解して取得すると、インターフェイスから返されたデータをより適切に処理できるようになります。この記事では、JavaScript を使用して HTTP ステータス コードを取得する方法と、具体的なコード例を紹介します。 1. HTTP ステータス コードとは何ですか? HTTP ステータス コードとは、ブラウザがサーバーへのリクエストを開始したときに、サービスが
