[英]Create a read-only/immutable copy of any object (including deep properties)
如何在JavaScript中創建對象的只讀/不可變版本,其屬性無法更改? 這也應該適用於任何子對象的屬性等。
我遇到的所有方法( Object.defineProperty
, Object.freeze
等)僅適用於對象的頂級屬性,但不適用於子對象。
(可能的用例:在特定模塊中創建/修改settings
或configuration
類型對象后,需要以不可變的形式將其公開給程序的其余模塊。)
經過一番思考后,我想出了這個解決方案。 適合我的需求,所以我想我會分享它的QnA風格。 如果您找到它們,請建議任何改進/問題。
/**
* Make the the specified object (deeply) immutable or "read-only", so that none of its
* properties (or sub-properties) can be modified. The converted object is returned.
* @param {object} obj Input object
*/
makeImmutable: function makeImmutable (obj) {
if ((typeof obj === "object" && obj !== null) ||
(Array.isArray? Array.isArray(obj): obj instanceof Array) ||
(typeof obj === "function")) {
Object.freeze(obj);
for (var key in obj) {
if (obj.hasOwnProperty(key)) {
makeImmutable(obj[key]);
}
}
}
return obj;
}
編輯:簡化代碼。 現在也正確處理數組。
這個解決方案很感興趣。
/** * Make the the specified object (deeply) immutable or "read-only", so that none of its * properties (or sub-properties) can be modified. The converted object is returned. * @param {object} obj Input object */ makeImmutable: function makeImmutable(obj) { if ((typeof obj === "object" && obj !== null) || (Array.isArray ? Array.isArray(obj) : obj instanceof Array) || (typeof obj === "function")) { Object.freeze(obj); for (var key in obj) { if (obj.hasOwnProperty(key)) { makeImmutable(obj[key]); } } } return obj; } var newObj = { thisArrayOfObjects: [{ propertyOne: 'value1', propertyTwo: 'value2' }] }; newObj.thisArrayOfObjects.push({ propertyBefore: 'before3' }); console.log('newObj', newObj); $('#viewer').append('newObj: ' + JSON.stringify(newObj)); makeImmutable(newObj); console.log('imutable', newObj); $('#viewer').append('<br/><br/>imutable: ' + JSON.stringify(newObj)); try { newObj.thisArrayOfObjects.push({ propertyThree: 'value3' }); } catch (e) { $('#viewer').append('<br/><br/>immutable error: ' + e.message); console.log('immutable error:', e.message); }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script> <div id="viewer" />
好的答案已經。 這個是使用lodash
:
var _ = require('lodash');
使對象不可變:
/**
* Makes an Object immutable by (deep) freezing all own peoperties.
* @param {*} obj - Object to make immutable.
* @returns {*} The input Object.
*/
function deepFreeze(obj) {
if (_.isObject(obj) || _.isArray(obj) || _.isFunction(obj)) {
Object.freeze(obj);
_.forOwn(obj, deepFreeze);
}
return obj;
}
要創建一個不可變的克隆:
var frozenClone = deepFreeze(_.cloneDeep(obj));
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.