or...in语句解析
<script>
var json={a: 12, b: 5};
for(var i in json)
{
alert(i+'='+json[i]);
}
</script>
eval() 函数可计算某个字符串, 并执行其中的的 JavaScript 代码。
服务器端脚本代码:
<?php
$row=array('username'=>'lisi','password'=>'222222');
echo json_encode($row);
/*$data=array(
array('name'=>'zhangsan','age'=>18),
array('name'=>'lisi','age'=>30)
);
echo json_encode($data);
*/
?>
var json=eval('('+value+')'); 主要是针对关联数组
返回:"{name:'zhangsan',age:18}"
访问方式:json.username+json.password
var json=eval(value); 主要是针对索引数组
返回:"[{name:'zhangsan',age:18},{name:'lisi',age:20}]"
访问方式:json[0].name+json[0].age
注意:索引数组的解析也可以采用 var json=eval(value);
<script language="javascript" src="public.js"></script>
<script>
var xhr=createxhr(); //创建ajax对象, 代码见ajax | ajax封装GET和POST
xhr.open('post','demo05.php');
xhr.setRequestHeader('Content-type','application/x-www-form-urlencoded');
xhr.onreadystatechange=function(){
if(xhr.readyState==4 && xhr.status==200){
var value=xhr.responseText; //返回的是字符串
//1)
var json=eval('('+value+')'); //返回是json对象
alert(json.username+json.password);
//2)
//var json=eval(value); //返回是json数组对象
//alert(json[1].name+json[1].age);
}
};
xhr.send(null);
</script>
返回:"{name:’zhangsan’,age:18}"
解析格式:eval('('+value+')');
返回:"[{name:'zhangsan',age:18},{name:'lisi',age:20}]"
解析格式:eval(value);
也可以采用eval('('+value+')');
实例1:
<html>
<head>
<title>新建网页</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="description" content="" />
<meta name="keywords" content="" />
<script type="text/javascript">
function f1(){
//ajax去服务器获得json信息
var xhr=new XMLHttpRequest();
xhr.onreadystatechange=function(){
if(xhr.readyState==4 && xhr.status==200){
//alert(xhr.responseText);//字符串{"north":"wolf","helan":"pig","germany":"dog"}
var info=eval('('+xhr.responseText+')');
//也可写成:eval("var info="+xhr.responseText);
document.write(info.north);
document.write(info.helan);
document.write(info.germany);
}
}
xhr.open('get','03.php');
xhr.send(null);
}
//javascript把一个字符串变为对象
//var a='{"north":"wolf","helan":"pig","germany":"dog"}';
//eval(参数字符串)
//eval("var obj="+a);//eval('var obj={"north":"wolf","helan":"pig","germany":"dog"}');
//document.write(obj);//访问对象
</script>
</head>
<body>
<h2>静态网站,javascript对json的接收处理</h2>
<input type="button" value="触发" onclick="f1()" />
</body>
</html>
<?php
//对外提供json信息
header("Cache-Control:no-cache,must-revalidate");
$animal=array('north'=>'wolf','helan'=>'pig','germany'=>'dog');
echo json_encode($animal); //{"north":"wolf","helan":"pig","germany":"dog"}
?>
在javascript解析{"north":"wolf","helan":"pig","germany":"dog"}
采用:var info=eval('('+xhr.responseText+')'); 语法
也可写成:eval("var info="+xhr.responseText);
实例2:
<html>
<head>
<title>新建网页</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="description" content="" />
<meta name="keywords" content="" />
<script type="text/javascript">
function f1(){
//ajax去服务器获得json信息
var xhr=new XMLHttpRequest();
xhr.onreadystatechange=function(){
if(xhr.readyState==4 && xhr.status==200){
//alert(xhr.responseText);//数组 ["wolf","pig","dog"]
var info=eval(xhr.responseText);
document.write(info[0]+info[1]+info[2]);
}
}
xhr.open('get','03.php');
xhr.send(null);
}
</script>
</head>
<body>
<h2>静态网站,javascript对json的接收处理</h2>
<input type="button" value="触发" onclick="f1()" />
</body>
</html>
<?php
//对外提供json信息
header("Cache-Control:no-cache,must-revalidate");
$animal=array('wolf','pig','dog');
echo json_encode($animal); //["wolf","pig","dog"]
?>
在javascript解析["wolf","pig","dog"]时
采用:var info=eval(xhr.responseText);语法
实例3:
<html>
<head>
<title>新建网页</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="description" content="" />
<meta name="keywords" content="" />
<script type="text/javascript">
function f1(){
//ajax去服务器获得json信息
var xhr=new XMLHttpRequest();
xhr.onreadystatechange=function(){
if(xhr.readyState==4 && xhr.status==200){
var s="";
//alert(xhr.responseText);//数组对象[{"id":1,"name":"xutao","sex":"\u7537","age":30},...]
var info=eval(xhr.responseText);
for(var i=0;i<info.length;i++){
s +=info[i].id + "--" + info[i].name + "--" + info[i].sex + "--" + info[i].age +"<br />";
}
document.getElementById("user").innerHTML=s;
}
}
xhr.open('get','info.php');
xhr.send(null);
}
</script>
</head>
<body>
<h2>静态网站,javascript对json的接收处理</h2>
<input type="button" value="触发" onclick="f1()" />
<div id="user"></div>
</body>
</html>
<?php
$info=array(
array("id"=>1,"name"=>"zhangsan","sex"=>"男","age"=>30),
array("id"=>2,"name"=>"lisi","sex"=>"女","age"=>27),
array("id"=>3,"name"=>"wangwu","sex"=>"男","age"=>6)
);
echo json_encode($info);
/* [{"id":1,"name":"zhangsan","sex":"\u7537","age":30},
{"id":2,"name":"lisi","sex":"\u5973","age":27},
{"id":3,"name":"wuwang","sex":"\u7537","age":6}] */
?>
在javascript解析[{"id":1,"name":"zhangsan","sex":"\u7537","age":30},
{"id":2,"name":"lisi","sex":"\u5973","age":27},
{"id":3,"name":"wuwang","sex":"\u7537","age":6}]时
采用:var info=eval(xhr.responseText);语法
从数据库读取出来的二维数组,通过json_encode()编码后, 在javascript进行解析时也是采用上述语法。
日常开发中,我们经常会使用到 JSON.stringify 这个方法,特别是在需要进行序列化(深拷贝)的时候。它可以把我们的对象转换成一个 JSON 字符串,这个方法确实非常方便,但它也有一些不常被注意到的缺点。
首先,JSON.stringify 的使用场景非常广泛,比如说当我们需要把对象保存到本地存储时,或者需要在前后端之间传输数据时,都会用到它。它就像是一个神奇的转换器,让我们可以轻松地处理复杂的数据结构。
然而,这个看似完美的方法也有它的局限性。比如说,它无法处理函数、undefined、Symbol 等特殊类型的数据,这些数据在转换成 JSON 字符串时会被忽略掉。此外,如果对象中存在循环引用,JSON.stringify 也会报错。
对于初学者来说,这些问题可能不太容易发现,因为大多数时候我们处理的数据都是简单的对象和数组。但在实际开发中,了解这些细节能够帮助我们更好地利用 JSON.stringify,同时避免一些潜在的坑。
在开发过程中,JSON.stringify 是我们常用的工具,但是它也有一些小坑,特别是处理某些特殊情况时。下面,我们通过几个例子来了解一下这些局限性。
1. 函数问题
如果对象的属性是函数,这个属性在序列化时会丢失。
let person={
name: '小明',
greet: function () {
console.log(`你好,我是${ this.name }`)
}
}
console.log(JSON.stringify(person)); // {"name":"小明"}
解释:在上面的例子中,greet 函数在转换成 JSON 字符串后被丢弃了。
2. undefined 问题
如果对象的属性值是 undefined,这个属性在转换后也会消失。
let data={
age: undefined
}
console.log(JSON.stringify(data)); // {}
解释:在这个例子中,age 属性在转换后完全消失了。
3. 正则表达式问题
如果对象的属性是正则表达式,转换后会变成一个空对象。
let settings={
name: '配置',
pattern: /^a/,
display: function () {
console.log(`${ this.name }`)
}
}
console.log(JSON.stringify(settings)); // {"name":"配置","pattern":{}}
解释:这里的 pattern 正则表达式在转换后变成了一个空对象 {}。
4. 数组对象的问题
上述问题在数组对象中同样会出现。
let items=[
{
price: undefined
}
]
console.log(JSON.stringify(items)); // [{}]
解释:在数组对象中,price 属性的 undefined 值在转换后也被丢弃了。
1、特殊值的处理
对象属性中的特殊值
当 undefined、函数和 Symbol 作为对象属性值时,JSON.stringify 会忽略它们。
const data={
a: "文字",
b: undefined,
c: Symbol("符号"),
fn: function() {
return true;
}
};
console.log(JSON.stringify(data)); // "{"a":"文字"}"
解释:在上面的例子中,data 对象的 b、c 和 fn 属性在序列化后都被忽略了,只剩下属性 a 被保留。
数组元素中的特殊值
当 undefined、函数和 Symbol 作为数组元素时,JSON.stringify 会将它们序列化为 null。
const array=["文字", undefined, function aa() { return true; }, Symbol('符号')];
console.log(JSON.stringify(array)); // "["文字",null,null,null]"
解释:在这个例子中,数组中的 undefined、函数和 Symbol 都被转换成了 null,而不是被忽略。
独立的特殊值
当 undefined、函数和 Symbol 被独立序列化时,JSON.stringify 会直接返回 undefined。
console.log(JSON.stringify(function a (){console.log('a')})); // undefined
console.log(JSON.stringify(undefined)); // undefined
console.log(JSON.stringify(Symbol('符号'))); // undefined
解释:在这些情况下,JSON.stringify 并不会返回 JSON 字符串,而是直接返回 undefined,表示这些值无法被序列化。
2、顺序
在使用 JSON.stringify 进行序列化时,除了我们之前提到的特殊值处理外,还有一个需要注意的点就是对象属性的顺序问题。让我们通过具体的例子来了解这些特性。
非数组对象的属性顺序
对于非数组对象来说,属性的顺序在序列化后的 JSON 字符串中并不一定是按照我们定义的顺序出现的,尤其是当一些属性值被忽略时。
const data={
a: "文字",
b: undefined,
c: Symbol("符号"),
fn: function() {
return true;
},
d: "更多文字"
};
console.log(JSON.stringify(data)); // "{"a":"文字","d":"更多文字"}"
解释:在这个例子中,data 对象中的 b、c 和 fn 属性由于特殊值的原因被忽略了,最终的 JSON 字符串中只剩下 a 和 d 属性,而且顺序并没有保证。
数组元素的顺序
对于数组来说,元素的顺序在序列化后是可以保证的,即使数组中包含 undefined、函数和 Symbol 这些特殊值,它们会被转换成 null,但顺序不会改变。
const array=["文字", undefined, function aa() { return true; }, Symbol('符号'), "更多文字"];
console.log(JSON.stringify(array)); // "["文字",null,null,null,"更多文字"]"
解释:在这个例子中,数组中的 undefined、函数和 Symbol 被转换成 null,但数组中元素的顺序保持不变。
3、利用 toJSON 方法自定义序列化结果
在使用 JSON.stringify 进行对象序列化时,有一个非常有趣且强大的特性——如果被转换的值中包含 toJSON() 方法,那么序列化的结果将由 toJSON() 方法返回的值决定,而忽略对象的其他属性。这为我们提供了很大的灵活性,可以自定义序列化结果。让我们通过具体的例子来了解这个特性。
自定义序列化结果
当一个对象包含 toJSON() 方法时,JSON.stringify 会调用这个方法,并使用其返回值作为最终的序列化结果。
const data={
say: "你好,JSON.stringify",
toJSON: function() {
return "今天我学到了";
}
};
console.log(JSON.stringify(data)); // "今天我学到了"
解释:在这个例子中,虽然 data 对象包含了 say 属性,但因为它定义了 toJSON() 方法,序列化时会调用这个方法,并使用它的返回值 "今天我学到了" 作为最终结果。
实际应用场景
这个特性可以在多种场景中应用,比如在对象序列化时需要隐藏某些敏感信息,或者只返回对象中的关键信息。
const user={
name: "小明",
password: "123456",
toJSON: function() {
return {
name: this.name
};
}
};
console.log(JSON.stringify(user)); // "{"name":"小明"}"
解释:在这个例子中,user 对象通过 toJSON() 方法自定义了序列化结果,只返回 name 属性,隐藏了敏感的 password 信息。
4、Date 对象的序列化技巧
在使用 JSON.stringify 时,处理日期对象是一个常见的需求。幸运的是,JSON.stringify 可以很好地处理 Date 对象,因为 Date 对象本身实现了 toJSON() 方法。让我们通过具体例子来了解这一特性,并探讨如何在实际开发中灵活运用。
日期对象的序列化
当我们将 Date 对象传给 JSON.stringify 时,它会调用 Date 对象的 toJSON() 方法,该方法等同于 Date.toISOString(),返回一个标准的 ISO 字符串格式。
const data={
now: new Date()
};
console.log(JSON.stringify(data)); // "{"now":"2024-06-16T12:43:13.577Z"}"
解释:在这个例子中,data 对象中的 now 属性是一个 Date 对象,序列化后变成了 ISO 8601 格式的字符串,表示日期和时间。
Date 对象的 toJSON() 方法
Date 对象的 toJSON() 方法实际上返回的是 Date.toISOString() 的结果,这使得日期在序列化后以字符串形式表示,并且格式统一,方便数据传输和存储。
const now=new Date();
console.log(now.toJSON()); // "2024-06-16T12:43:13.577Z"
console.log(now.toISOString()); // "2024-06-16T12:43:13.577Z"
解释:无论是直接调用 toJSON() 还是 toISOString(),得到的结果都是同样的 ISO 字符串格式。
实际应用场景
在实际开发中,我们经常需要将日期对象转换为 JSON 字符串,以便在前后端之间传输数据或存储到数据库中。统一的 ISO 格式不仅简洁,还可以方便地在不同系统和语言之间解析和使用。
const event={
name: "会议",
date: new Date("2024-08-11T10:00:00Z")
};
console.log(JSON.stringify(event)); // "{"name":"会议","date":"2024-08-11T10:00:00.000Z"}"
解释:在这个例子中,我们创建了一个包含日期的事件对象,序列化后,日期属性被转换成 ISO 字符串,方便在网络上传输。
5、的特殊数值处理:NaN、Infinity 和 null 的处理方式
在使用 JSON.stringify 时,处理特殊数值也是一个需要注意的问题。NaN、Infinity 和 null 在序列化时都会被处理为 null。让我们通过一些具体的例子来详细了解这一特性。
数值 NaN 和 Infinity 的序列化
当我们将 NaN 或 Infinity 传给 JSON.stringify 时,它们会被转换成 null。
console.log(JSON.stringify(NaN)); // "null"
console.log(JSON.stringify(Infinity)); // "null"
解释:在这个例子中,无论是 NaN 还是 Infinity,都被序列化为 "null",这是因为 JSON 不支持这两种特殊数值,所以将其转换为 null 来表示。
null 的序列化
当我们将 null 传给 JSON.stringify 时,它会被直接转换为字符串 "null"。
console.log(JSON.stringify(null)); // "null"
解释:null 是 JSON 支持的一个特殊值,所以它在序列化时会被保留为 "null" 字符串。
对象和数组中的特殊数值
当 NaN、Infinity 和 null 作为对象属性值或数组元素时,它们会被转换为 null。
const data={
num1: NaN,
num2: Infinity,
num3: null
};
console.log(JSON.stringify(data)); // "{"num1":null,"num2":null,"num3":null}"
const array=[NaN, Infinity, null];
console.log(JSON.stringify(array)); // "[null,null,null]"
解释:在这个例子中,data 对象中的 num1 和 num2 属性值,及数组中的 NaN 和 Infinity 元素,都被转换为 null。
实际应用场景
理解这些特性有助于我们在实际开发中正确处理数据,特别是在数据传输和存储时,避免因为特殊数值导致的数据不一致问题。
const stats={
average: NaN,
max: Infinity,
min: null,
values: [1, 2, NaN, 4, Infinity]
};
console.log(JSON.stringify(stats));
// "{"average":null,"max":null,"min":null,"values":[1,2,null,4,null]}"
解释:在这个统计数据对象中,所有的 NaN 和 Infinity 值在序列化后都被转换为 null,保证了 JSON 数据的一致性。
6、包装对象处理:自动转换为原始值
在使用 JSON.stringify 时,有一个很重要的特性是,布尔值、数字和字符串的包装对象在序列化时会自动转换为它们对应的原始值。这一特性有助于确保序列化后的 JSON 数据更简洁和易于使用。让我们通过具体的例子来深入了解这一特性。
包装对象的序列化
当我们将 Number、String 和 Boolean 包装对象传给 JSON.stringify 时,它们会被自动转换为对应的原始值。
console.log(JSON.stringify([new Number(1), new String("false"), new Boolean(false)]));
// "[1,"false",false]"
解释:在这个例子中,new Number(1) 被转换为 1,new String("false") 被转换为 "false",new Boolean(false) 被转换为 false。这些包装对象在序列化时都被简化为原始值,确保 JSON 数据的简洁性。
7、枚举属性与非枚举属性
在使用 JSON.stringify 进行对象序列化时,有一个关键的特性是:它只会序列化对象的可枚举属性(enumerable properties)。这意味着非枚举属性会被忽略,从而确保序列化结果的简洁和预期。让我们通过具体的例子来详细了解这一特性。
枚举属性与非枚举属性的区别
在 JavaScript 中,对象的属性可以被标记为枚举属性或非枚举属性。JSON.stringify 只会序列化枚举属性,而忽略非枚举属性。
const data=Object.create(
null,
{
x: { value: 'json', enumerable: false },
y: { value: 'stringify', enumerable: true }
}
);
console.log(JSON.stringify(data)); // "{"y":"stringify"}"
解释:在这个例子中,data 对象的 x 属性被标记为非枚举属性,y 属性被标记为枚举属性。JSON.stringify 在序列化时忽略了 x 属性,只保留了 y 属性。
处理 Map、Set 等对象
类似地,对于 Map、Set 等对象,JSON.stringify 也只会序列化它们的可枚举属性,而这些对象的特殊数据结构本身不会被直接序列化。
const map=new Map();
map.set('a', 1);
map.set('b', 2);
const set=new Set();
set.add(1);
set.add(2);
console.log(JSON.stringify(map)); // "{}"
console.log(JSON.stringify(set)); // "{}"
解释:在这个例子中,map 和 set 对象的内部数据结构没有被序列化,而是返回了空对象。这是因为 Map 和 Set 的数据存储并不是作为对象的属性存在的。
实际应用场景
了解这个特性对于处理复杂对象结构非常重要,特别是在需要控制序列化结果的情况下。例如,可以通过定义非枚举属性来隐藏一些不需要序列化的内部数据。
const user={
name: '小明',
age: 25
};
Object.defineProperty(user, 'password', {
value: '123456',
enumerable: false
});
console.log(JSON.stringify(user)); // "{"name":"小明","age":25}"
解释:在这个例子中,我们通过 Object.defineProperty 将 password 属性标记为非枚举属性,从而在序列化时将其隐藏。
8、JSON.parse(JSON.stringify()) 的局限性
我们都知道,使用 JSON.parse(JSON.stringify()) 是实现深克隆的最简单和直接的方法。然而,由于序列化的各种特性,这种方法在实际应用中会带来许多问题,尤其是当对象存在循环引用时,会导致错误。让我们通过一个具体的例子来详细了解这些局限性。
循环引用的问题
当对象存在循环引用时,JSON.stringify() 会抛出错误,因为 JSON 不支持循环结构。
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
*/
解释:在这个例子中,obj 和 loopObj 形成了一个循环引用,这导致 JSON.stringify() 在处理时抛出了 TypeError 错误。
深克隆的替代方法
为了安全地进行深克隆,特别是处理循环引用,我们需要使用更复杂的方法。以下是两种常见的替代方案:
1. 使用递归和 Map 记录引用
function deepClone(obj, hash=new WeakMap()) {
if (obj===null) return null;
if (typeof obj !=="object") return obj;
if (hash.has(obj)) return hash.get(obj);
const cloneObj=Array.isArray(obj) ? [] : {};
hash.set(obj, cloneObj);
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
cloneObj[key]=deepClone(obj[key], hash);
}
}
return cloneObj;
}
const newObj=deepClone(obj);
console.log(newObj);
解释:这个 deepClone 函数使用 WeakMap 来记录已经克隆过的对象,避免了循环引用的问题。
2. 使用第三方库
如果不想手动实现深克隆,可以使用现成的第三方库,如 lodash 提供的 _.cloneDeep 方法。
const _=require('lodash');
const newObj=_.cloneDeep(obj);
console.log(newObj);
解释:lodash 的 _.cloneDeep 方法能够处理大多数复杂情况,包括循环引用。
9、Symbol 属性的序列化问题
在使用 JSON.stringify 进行对象序列化时,有一个需要特别注意的点:如果对象的属性使用 Symbol 作为键,这些属性会被完全忽略,即使在 replacer 参数中显式包含也无效。让我们通过具体的例子来详细了解这一特性。
Symbol 属性的序列化
当对象的属性使用 Symbol 作为键时,JSON.stringify 会忽略这些属性,不会将它们包含在序列化结果中。
const data={ [Symbol.for("json")]: "stringify" };
console.log(JSON.stringify(data)); // "{}"
解释:在这个例子中,data 对象的属性键是一个 Symbol,所以在序列化时,这个属性被完全忽略了。
使用 replacer 参数
即使我们在 JSON.stringify 的 replacer 参数中显式包含处理 Symbol 属性的逻辑,这些属性仍然会被忽略。
const data={ [Symbol.for("json")]: "stringify" };
console.log(JSON.stringify(data, function(k, v) {
if (typeof k==="symbol") {
return v;
}
})); // "undefined"
解释:在这个例子中,replacer 函数试图检查 Symbol 类型的键并返回其值,但 JSON.stringify 仍然忽略了该属性,结果为undefined。
第二个参数 replacer 的妙用
在使用 JSON.stringify 进行对象序列化时,除了常见的用法,还有一些高级功能可以通过第二个参数 replacer 实现。replacer 可以是一个函数或数组,用于定制序列化的结果。让我们通过具体的例子来详细了解这些用法。
1. 使用 replacer 参数作为函数
当 replacer 参数是一个函数时,它会在每个属性值被序列化之前调用,类似于数组方法中的 map 和 filter。该函数接收两个参数:键和值。
const data={
a: "aaa",
b: undefined,
c: Symbol("dd"),
fn: function() {
return true;
}
};
// 不使用 replacer 参数
console.log(JSON.stringify(data));
// "{"a":"aaa"}"
// 使用 replacer 参数作为函数
console.log(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 }"}"
解释:在这个例子中,replacer 函数将 undefined、Symbol 和函数转换为字符串,使得它们能够被序列化。
2. 第一次调用 replacer 函数的特殊情况
当 replacer 函数被第一次调用时,传入的第一个参数并不是对象的第一个键值对,而是一个空字符串作为键,整个对象作为值。
const data={
a: 2,
b: 3,
c: 4,
d: 5
};
console.log(JSON.stringify(data, (key, value)=> {
console.log(value);
return value;
}));
// The first argument passed to the replacer function is
// {"":{a: 2, b: 3, c: 4, d: 5}}
// 2
// 3
// 4
// 5
// {a: 2, b: 3, c: 4, d: 5}
3. 使用 replacer 函数实现对象的 map 功能
我们可以利用 replacer 函数手动实现类似于数组 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));
};
console.log(objMap(data, (key, value)=> {
if (value % 2===0) {
return value / 2;
}
return value;
}));
// {a: 1, b: 3, c: 2, d: 5}
4. 使用 replacer 参数作为数组
当 replacer 参数是一个数组时,数组中的值表示要被序列化到 JSON 字符串中的属性名。
const jsonObj={
name: "JSON.stringify",
params: "obj,replacer,space"
};
// 仅保留 params 属性的值
console.log(JSON.stringify(jsonObj, ["params"]));
// "{"params":"obj,replacer,space"}"
解释:在这个例子中,replacer 数组指定只序列化 params 属性,其他属性会被忽略。
第三个参数:控制输出格式的 space 参数
在使用 JSON.stringify 进行对象序列化时,第三个参数 space 用于控制生成的 JSON 字符串中的空格和缩进。这个参数可以显著提高输出结果的可读性。让我们通过具体的例子来了解 space 参数的作用和用法。
1. space 参数的基本用法
space 参数可以是一个数字或字符串。数字表示每一级嵌套的缩进空格数,字符串则用于每一级嵌套的缩进字符。
const tiedan={
name: "Jhon",
describe: "JSON.stringify()",
emotion: "like"
};
// 使用 "--" 作为缩进字符
console.log(JSON.stringify(tiedan, null, "--"));
/* 输出结果如下:
{
--"name": "Jhon",
--"describe": "JSON.stringify()",
--"emotion": "like"
}
*/
// 使用 2 个空格作为缩进字符
console.log(JSON.stringify(tiedan, null, 2));
/* 输出结果如下:
{
"name": "Jhon",
"describe": "JSON.stringify()",
"emotion": "like"
}
*/
解释:在第一个例子中,space 参数是字符串 "--",所以每一级嵌套使用两个连字符作为缩进。在第二个例子中,space 参数是数字 2,所以每一级嵌套使用两个空格作为缩进。
2. 数字作为 space 参数
当 space 参数是数字时,它表示每一级嵌套的缩进空格数,最大值为 10。
const data={
level1: {
level2: {
level3: "deep"
}
}
};
// 使用 4 个空格作为缩进字符
console.log(JSON.stringify(data, null, 4));
/* 输出结果如下:
{
"level1": {
"level2": {
"level3": "deep"
}
}
}
*/
解释:在这个例子中,space 参数是数字 4,所以每一级嵌套使用四个空格作为缩进。
在这篇文章中,我们深入探讨了 JSON.stringify 的多种高级用法,从特殊值处理到如何使用 replacer 参数定制序列化结果,再到使用 space 参数美化输出。希望通过这些实例,你能更好地掌握和运用 JSON.stringify,让你的前端开发更加高效和灵活。
SON(JavaScript Object Notation)是从JavaScript派生的一个独立于语言的文件。JSON文件是纯文本文件,而不是二进制代码。这种文件格式是可读的,任何文本编辑器都可以打开和编辑JSON文件。
此文件格式没有大小限制,因此数据大小可能很大很大。但是,如果文件太大,则存储的数据可能显示为随机的。这可能会导致难以理解整体内容。在这种情况下,你可以使用一些程序来查看此类JSON文件,我们在下面列出了这些文件。
JSON文件的文件名附加了一个.JSON扩展名。与XML类似,它是一种数据表示格式。由于以这种格式存储数据和配置文件很容易,大多数人都使用它。以下是为不同系统打开JSON文件的几种方法。
你可以使用记事本打开.json文件并进行更改。虽然JSON文件很容易理解,但如果文件太大,内置记事本可能会混淆数据。为了使文件更易于理解或组织,你可以使用Notepad++。以下是如何在Windows上使用记事本打开JSON文件。
1、启动记事本/Notepad++。
2、单击左上角的“文件”选项。
3、选择“打开…”选项。
4、在文件名搜索栏上搜索JSON文件。
5、单击“打开”按钮。
在完成这些步骤后,以下是你可以做的事情,使你的JSON文件在Notepad++上看起来更有条理。
1、单击“插件”选项,然后选择“插件管理…”选项。
2、搜索JSON并选择JSON Viewer选项。
3、单击右上角的“安装”选项。
4、单击确认框中的“是”。
5、安装插件后,再次单击“插件”选项。
6、选择JSON查看器选项,然后单击格式化JSON。
Apple Text Edit是macOS附带的一款软件。它是一个内置的文字处理器和文本编辑器平台。使用此软件,你可以在Mac上轻松打开和编辑JSON文件。以下是如何查看它。
1、在Mac设备上打开TextEdit。
2、单击“文件”并选择“打开”选项。
3、导航到JSON文件并单击它。
Vim是UNIX的Vi编辑器的著名继承者。这是一个免费的文件打开软件,可以让你查看和更改你的文件。这个程序最初是为Linux制作的。然而,他们最终为不同的系统创建了各种版本的编辑器,包括Windows和Mac。以下是如何使用它打开JSON文件。
1、复制JSON文件的路径并启动Vim。
2、输入“vim ”(后面有个空格)并从剪贴板粘贴路径。
3、然后按Enter键。
Mozilla Firefox是查看JSON文件的最佳平台之一。除了.json扩展之外,Mozilla firefox还支持以下文件:HTML、CSS、MFL和CHM。与大多数程序不同,Firefox以人类可读的格式打开文件。在执行以下步骤之前,请确保你已经下载了Firefox浏览器。
1、转到文件资源管理器并导航到JSON文件。
2、右键单击它,然后选择“属性”选项。
3、单击“文件类型”下的“更改…”按钮。
4、搜索Mozilla Firefox并点击它。如果你在菜单上找不到它,请按底部的“更多应用程序”选项,然后再次搜索。
5、单击“确定”按钮。
6、同时单击“属性”选项卡上的“确定”。
7、现在,点击JSON文件将其打开。该文件将显示在firefox选项卡中。
你可以在Chrome上轻松打开JSON文件。然而,大数据可能看起来杂乱无章,难以理解。添加扩展名使JSON文件易于阅读。数据看起来更有组织性和格式。你可以在Windows、Linux以及Macbook上使用此方法。
1、打开Chrome并转到Chrome Web Store。
2、在搜索栏上搜索JSON Viewer,然后按enter按钮。
3、打开要添加的扩展。
4、单击“添加到Chrome”选项。
5、在确认框中选择“添加扩展名”。
6、将扩展与你的设备同步。
7、现在,打开文件资源管理器并导航到JSON文件。
8、在文件上单击鼠标右键,然后选择“属性”选项。
9、在“文件类型”下,单击“更改…”选项。
10、搜索谷歌浏览器并点击它。
11、单击“确定”。
12、同时单击“属性”选项卡上的“确定”按钮。
13、返回JSON文件并打开它。你将在一个新的chrome选项卡中查看该文件。
有各种在线工具,如JSON Editor online,可以用来在设备上打开JSON文件。这些文件打开工具非常容易使用。要查看你的文件,你所需要的只是正确的互联网连接。以下是如何打开它。
1、打开web浏览器,在线搜索JSON编辑器。
2、单击右上角的“打开”图标。
3、选择从磁盘打开选项。
4、搜索你的JSON文件并单击它。
5、单击“打开”选项。
*请认真填写需求信息,我们会在24小时内与您取得联系。