別用JSON拷貝

前端精髓發表於2019-01-27

JSON的語法可以表示以下三種型別的值。

簡單值:使用與JavaScript相同的語法,可以在JSON中表示字串、數值、布林值和 null 。但JSON不支援JavaScript中的特殊值 undefined 。

物件:物件作為一種複雜資料型別,表示的是一組有序的鍵值對兒。而每個鍵值對兒中的值可以是簡單值,也可以是複雜資料型別的值。

陣列:陣列也是一種複雜資料型別,表示一組有序的值的列表,可以通過數值索引來訪問其中的值。陣列的值也可以是任意型別——簡單值、物件或陣列。

JSON不支援變數、函式或物件例項,它就是一種表示結構化資料的格式,雖然與JavaScript中表示資料的某些語法相同,但它並不侷限於JavaScript的範疇。

早期的JSON解析器基本上就是使用JavaScript的 eval() 函式。由於JSON是JavaScript語法的子集,因此 eval() 函式可以解析、解釋並返回JavaScript物件和陣列。ECMAScript 5對解析JSON的行為進行規範,定義了全域性物件 JSON 。JSON物件有兩個方法: stringify()parse() 。在最簡單的情況下,這兩個方法分別用於把JavaScript物件序列化為JSON字串和把JSON字串解析為原生JavaScript值。

在序列化JavaScript物件時,所有函式及原型成員都會被有意忽略,不體現在結果中。此外,值為 undefined 的任何屬性也都會被跳過。結果中最終都是值為有效JSON資料型別的例項屬性。將JSON字串直接傳遞給 JSON.parse() 就可以得到相應的JavaScript值。

常常會用 JSON.parseJSON.stringify 來深拷貝,如下面這樣。

let obb = {
    a: 1,
    b: function () {
        console.log('b')
    },
    c: /\d+/
}
JSON.parse(JSON.stringify(obb)) // {a: 1, c: {}}
複製程式碼

因為JSON對有些資料不支援,所以無法完全拷貝各種資料型別的值。如果想完全拷貝,可以這樣。

function deepClone (obj) {
    if (obj === null) return null
    if (typeof obj !== 'object') return obj
    if (obj instanceof RegExp) return new RegExp(obj)
    if (obj instanceof Date) return new Date(obj)
    let newObj = new obj.constructor
    for (let key in obj) {
        newObj[key] = deepClone(obj[key])
    }
    return newObj
}
複製程式碼

相關文章