通常,您必须传递一个对象作为参数。访问这些对象的函数通过引用传递,并且可以更改原始对象。根据情况可能是不希望的结果。因此,有一种冻结对象的方法。我知道Object.freeze()
但是它不会影响其中的对象/数组。
例如
a = { arr: [1,2,3]};
Object.freeze(a);
a.arr.push(4); // still works
答案 0 :(得分:1)
如果您查看MDN,那里有一个建议使用DeepFreeze功能的函数,但是它并不安全。我个人有一个ES5版本来异步迭代。对于ES6,遵循这些思路的某些方法可能会起作用,但是我并未对其进行全面测试:
function deepFreeze(o,promises,oldestParent){
promises = promises || [];
oldestParent = oldestParent || o;
promises.push(
Promise.resolve().then(function(){
Object.values(Object.freeze(o)).forEach(function(d,i){
typeof d === "object" && deepFreeze(d,promises,oldestParent);
});
return oldestParent;
})
);
return Promise.all(promises).then((a)=>a[0]);
}
var o = {a:3,b:{test:1,test2:2},c:1};
deepFreeze(o).then(function(x){console.log(x)}); //o is deep frozen
警告:我假设您对象的属性是可枚举的,否则请使用getOwnPropertyNames
。
答案 1 :(得分:1)
您可以像这样创建一个非常简单的递归解决方案:
let a = {
arr: [1, 2, 3],
name: "A. Bc"
};
const deepFreeze = o => {
for (let [key, value] of Object.entries(o)) {
if (o.hasOwnProperty(key) && typeof value == "object") {
deepFreeze(value);
}
}
Object.freeze(o);
return o;
}
deepFreeze(a);
try {
a.arr.push(4);
} catch(e) {
console.log("Error: ", e);
}
console.log(a);
答案 2 :(得分:0)
检出deep-freeze
会在对象上递归Object.freeze()
这是他们的实现方式
function deepFreeze (o) {
Object.freeze(o);
Object.getOwnPropertyNames(o).forEach(function (prop) {
if (o.hasOwnProperty(prop)
&& o[prop] !== null
&& (typeof o[prop] === "object" || typeof o[prop] === "function")
&& !Object.isFrozen(o[prop])) {
deepFreeze(o[prop]);
}
});
return o;
};
答案 3 :(得分:0)
function deepFreeze(object) {
// Retrieve the property names defined on object
var propNames = Object.getOwnPropertyNames(object);
// Freeze properties before freezing self
for (let name of propNames) {
let value = object[name];
object[name] = value && typeof value === "object" ?
deepFreeze(value) : value;
}
return Object.freeze(object);
}
let a = { arr: [1,2,3]};
deepFreeze(a);
a.arr.push(4); // TypeError: Cannot add property 3, object is not extensible
(第二个代码[第二个灰色区域])https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze#What_is_shallow_freeze
谢谢:)
答案 4 :(得分:0)
要深度冻结所有可枚举的属性(ES2015 +):
// Recursively freeze an object
const deepFreeze = x => {
Object.freeze(x)
Object.values(x).forEach(deepFreeze)
}
如果您有循环引用:
// Recursively freeze an object with circular references
const deepFreeze = x => {
Object.freeze(x)
Object.values(x).filter(x => !Object.isFrozen(x)).forEach(deepFreeze)
}
如果您还还必须冻结任何浅冷冻的东西(速度稍慢):
// Recursively deep freeze an object with circular references
const deepFreeze = (x, frozen = []) => {
if (frozen.includes(x)) return null
frozen.push(x)
Object.freeze(x)
Object.values(x).forEach(x => deepFreeze(x, frozen))
}
tldr;两线:
const deepFreeze = (x, frozen = []) => frozen.includes(x) ||
frozen.push(Object.freeze(x)) && Object.values(x).forEach(x => deepFreeze(x, frozen))
答案 5 :(得分:0)
// when we iterate over obj keys, make sure keys that their value is object are passed
const isObject=(val)=>val && typeof val==='object'
function deepFreeze(obj){
// if object is already frozen, skip it
if (isObject(obj) && !Object.isFrozen(obj)){
Object.keys(obj).forEach((key)=>deepFreeze(obj[key]))
}
return obj
}