1. 程式人生 > >JavaScript 中的不可變對象(Immutable Objects)

JavaScript 中的不可變對象(Immutable Objects)

col es5 還需要 scrip 情況 解決 創建 logs 方案

  默認情況下,JavaScript 中的對象是可變的。我們可以更改原始值(字符串,數字等)和對象。我們來看看這個對象:

let obj = {
    num: 10,
    obj: {
        content: "mutable object"
    }
}

  你可以輕松地改變它:

obj.num = 5;
obj.obj = { content: "changed!" }
 
console.log(obj);
 
// {
//     num: 5,
//     obj: {
//         content: "changed!"
//     }
// }

  非常明確是吧?那麽,我們有什麽辦法使對象不可變呢?

1、讓我們試用 const !

  很好的嘗試,但是不起作用。如果你嘗試一下,你會發現:這種辦法根本就不起作用。const 關鍵字只是修改了某個變量名和其值之間的鏈接,而不是實際值。您仍然可以像上面所做的那樣在 const 對象中更改這兩個原始值和對象。例如:

const obj = {
    num: 10,
    obj: {
        content: "mutable object"
    }
}
 
obj.num = 5;
obj.obj = { content: "changed!" }
 
console.log(obj);
 
// {
//     num: 5,
//     obj: {
// content: "changed!" // } // }

2、繼續嘗試:Object.freeze()。

  有很多關於 ES2015 新特性的文章和討論。我們知道 ES2015 比 ES5 更好。例如,我們可以使用一個Object 方法來實現我們的目的:Object.freeze()。該方法使對象的原始屬性不可變。我們把這個方法應用到我們原來的 obj 對象上:

Object.freeze(obj);
obj.num = 5;
obj.obj = { content: "changed!" }
 
console.log(obj);
 
// {
//     num: 10,
//     obj: {
// content: "changed!" // } // }

  結果比原先的嘗試稍後好一點,原始值現在已經修復,不可更改,但是我們仍然可以更改嵌套對象。

3、最終解決方案

  為了使對象完全不可變,我們還需要freeze()所有的嵌套對象。例如:

function deepFreeze(obj) {
    var propNames = Object.getOwnPropertyNames(obj);
    propNames.forEach(function(name) {
        var prop = obj[name];
        if (typeof prop == object && prop !== null) {
            deepFreeze(prop);
        }
    });
    return Object.freeze(obj);
}

  使用這個函數,現在我們可以創建完全不可變的對象:

deepFreeze(obj);
obj.num = 5;
obj.obj = { content: "changed!" }
 
console.log(obj);
 
// {
//     num: 10,
//     obj: {
//         content: "mutable object"
//     }
// }

JavaScript 中的不可變對象(Immutable Objects)