基本介紹
JSON的全稱是JavaScript Object Notation绅你,它并不是編程語言纪岁,而是一種可以在服務器和客戶端之間傳輸?shù)臄?shù)據(jù)格式凑队,本來是JavaScript的子集,但現(xiàn)在已獨立存在于各種編程語言中幔翰。
它有以下使用場景
- 網絡數(shù)據(jù)傳遞時漩氨,比如http請求中參數(shù)
- 項目里某些配置文件,比如package.json文件
- 非關系型數(shù)據(jù)庫(NoSQL)將json作為存儲格式
語法
它的文件以 .json 為后綴名遗增,但json文件頂層的代碼有嚴格限制叫惊,只能寫以下三種,不然代碼會直接標紅~
1做修、簡單值
數(shù)字(Number)霍狰、字符串(String,不支持單引號)饰及、布爾類型(Boolean)蔗坯、null類型
2、對象值
由key燎含、value組成宾濒,key是字符串類型,必須添加雙引號屏箍,值可以是簡單值绘梦、對象值橘忱、數(shù)組值
3、數(shù)組值
簡單值卸奉、對象值钝诚、數(shù)組值
序列化 stringify
在http請求中攜帶參數(shù)經常用到json格式,但我們一般不會在代碼中直接使用json榄棵,因為json數(shù)據(jù)中操作屬性并不方便敲长,大多數(shù)時候是使用對象,將對象轉成json格式就可以通過 stringify 方法秉继。
stringify方法有三個參數(shù)
- 參數(shù)一(必傳)祈噪,傳入一個對象,表示對于哪個對象進行stringify操作
- 參數(shù)二(可選)尚辑,傳入數(shù)組或者函數(shù)辑鲤,數(shù)組里包括對象的key值,表示對于對象中的指定key值的數(shù)據(jù)進行序列化杠茬,傳入函數(shù)表示對指定的key/value值進行操作
- 參數(shù)三(可選)月褥,用于改變序列化之后的json數(shù)據(jù)展現(xiàn)格式
我們對以下對象進行操作
const user = {
name: "alice",
age: 20,
friends: ["lisa", "macus", "windy"],
info: {
teacher: "kiki",
},
};
直接轉換
當只傳入一個參數(shù)時,進行基本的序列化操作
const str1 = JSON.stringify(user);
console.log(str1);
操作指定的key值
const str2 = JSON.stringify(user, ["name", "friends"]);
const str3 = JSON.stringify(user, (key, value) => {
if (key === "age") {
return value + 1;
}
return value;
});
console.log(str2);
console.log(str3);
當傳入第二個參數(shù)時瓢喉,傳入數(shù)組宁赤,表示只對 key值為“name”,“friends”的數(shù)據(jù)進行序列化栓票;傳入函數(shù)决左,表示操作 key 值為“age”的時候,value+1
改變json展現(xiàn)格式
const str4 = JSON.stringify(user, null, 2);
const str5 = JSON.stringify(user, null, "*");
console.log(str4);
console.log(str5);
傳入第三個參數(shù)走贪,2表示換行空2格佛猛,* 表示換行及每行內容前加 * 號
toJson方法
如果原對象中有toJSON方法,那么stringify方法直接調用toJSON方法坠狡。我們給上面的對象加上toJSON方法继找,所有的stringify方法的執(zhí)行結果都會變化。
const user = {
name: "alice",
age: 20,
friends: ["lisa", "macus", "windy"],
info: {
teacher: "kiki",
},
toJSON(){
return 'hello world'
}
};
const str1 = JSON.stringify(user);
const str2 = JSON.stringify(user, ["name", "friends"]);
const str3 = JSON.stringify(user, (key, value) => {
if (key === "age") {
return value + 1;
}
return value;
});
const str4 = JSON.stringify(user, null, 2);
const str5 = JSON.stringify(user, null, "*");
console.log(str1);
console.log(str2);
console.log(str3);
console.log(str4);
console.log(str5);
stringify方法的執(zhí)行結果都變成了 toJSON 方法的返回值
解析 parse
接口請求返回的參數(shù)中一般是json數(shù)據(jù)逃沿,我們要使用首先得通過parse方法將它轉成對象婴渡。
parse方法可以接收兩個參數(shù)
- 參數(shù)一(必傳),json數(shù)據(jù)凯亮,表示將哪一個json數(shù)據(jù)轉成對象
- 參數(shù)二(可選)边臼,傳入函數(shù),表示對指定的key/value值進行操作
const str =
'{"name":"alice","age":21,"friends":["lisa","macus","windy"],"info":{"teacher":"kiki"}}';
const obj1 = JSON.parse(str)
const obj2 = JSON.parse(str, (key, value)=>{
if(key === 'age'){
return value - 1
}
return value
})
console.log(obj1)
console.log(obj2)
傳入函數(shù)触幼,處理 key值為age時的數(shù)據(jù)硼瓣,此時操作 value - 1
拷貝
拷貝有以下幾種形式,拷貝出來的內存地址指向不一樣
直接賦值
通過等于符號可以將一個對象賦值給另一個對象置谦。
const user = {
name: "alice",
info: {
hobbies: "tennis",
},
};
const person = user;
user.name = "lisa";
console.log("user", user);
console.log("person", person);
但它們其實指向的是同一個對象堂鲤,如果操作其中一個對象的值,另外一個對象也會發(fā)生變化
在內存中表現(xiàn)如下
淺拷貝
淺拷貝只會遍歷一層媒峡,如果對象中還有value值為對象或者數(shù)組的情況瘟栖,那么更深一層不會被拷貝,展開運算符或者Object.assign可以進行淺拷貝谅阿。
const user = {
name: "alice",
info: {
hobbies: "tennis",
},
};
const consumer = { ...user };
user.name = "lisa";
user.info.hobbies = "swimming";
console.log("user", user);
console.log("consumer", consumer);
淺拷貝后半哟,user和consumer已經不是同一個對象了,但他們倆當中的info仍然指向同一個對象签餐,修改其中一個info中的屬性寓涨,另一個也會變化
在內存中表現(xiàn)如下
深拷貝
深拷貝表示拷貝出來的對象與原對象完全無關,操作任意屬性都不會互相影響氯檐,通過 stringify 和 parse 方法可以實現(xiàn)深拷貝戒良。
const user = {
name: "alice",
info: {
hobbies: "tennis",
},
};
const human = JSON.parse(JSON.stringify(user));
user.name = "lisa";
user.info.hobbies = "swimming";
console.log("user", user);
console.log("human", human);
此時user和human不是指向同一個對象,他們中的info對象也不是同一個對象
在內存中表現(xiàn)如下
stringify和parse實現(xiàn)深拷貝存在問題
雖然stringify和parse可以實現(xiàn)深拷貝冠摄,但是這種方式仍存在一些問題糯崎,如果對象中存在【方法、undefined河泳、Symbol】沃呢,會直接被移除
const user = {
name: "alice",
height: undefined,
[Symbol("age")]: 20,
info: {
hobbies: "tennis",
},
study() {
console.log("I love reading~");
},
};
const people = JSON.parse(JSON.stringify(user));
console.log("user", user);
console.log("person", people);
只剩下符合json規(guī)范的數(shù)據(jù)
因為存在這種問題,所以一般不會用stringify和parse方法拆挥,可以自己編寫處理深拷貝的方法薄霜,至于自定義深拷貝方法,留在后面的文章中詳細介紹纸兔。
以上就是json相關內容黄锤,關于js高級,還有很多需要開發(fā)者掌握的地方食拜,可以看看我寫的其他博文鸵熟,持續(xù)更新中~