如何更新对象属性的可枚举?
Posted
技术标签:
【中文标题】如何更新对象属性的可枚举?【英文标题】:How to update the enumerable of an object property? 【发布时间】:2017-07-12 14:53:47 【问题描述】:我定义一个对象如下:
var obj = ;
var name = "nonenumerable";
var value = "hello world";
Object.defineProperty(obj, name, value: value,
writable : true,
enumerable : false,
configurable : true
);
console.log(obj);
//output in code snippet console:
//output in browser console: nonenumerable: "hello world"
现在我想将对象存储到我的本地存储中
localStorage.setItem("localObj", JSON.stringify(obj));
我知道 JsonObjects 不包括“不可枚举”,因此我的属性没有被存储。我的问题是我将该对象用作一种“哈希表”。
var obj =
1: id: 1, start: 3, end: 6 ,
2: id: 2, start: 5, end: 8 ,
3: id: 3, start: 2, end: 4
;
Object.defineProperty(obj, "all", value: ,
writable : true,
enumerable : false,
configurable : true
);
obj.all.start = 0;
obj.all.end = 10;
function setStart(id, add)
if(add) obj[id].start += 1;
else obj[id].start -= 1
updateContent("start", id, obj[id].start);
function setAllStart(start, add)
if(add) obj.all.start += 1;
else obj.all.start -= 1
updateContent("start", "all", obj.all.start);
for(id in obj)
obj[id].start = obj.all.start;
updateContent("start", id, obj[id].start);
function setEnd(id, add)
if(add) obj[id].end += 1;
else obj[id].end -= 1
updateContent("end", id, obj[id].end);
function setAllEnd(start, add)
if(add) obj.all.end += 1;
else obj.all.end -= 1
updateContent("end", "all", obj.all.end);
for(id in obj)
obj[id].end = obj.all.end;
updateContent("end", id, obj[id].end);
function updateContent(selector, id, content)
document.querySelector("#" + selector + "-" + id).innerhtml = content;
.value
display: inline-block;
<div>
AllStart:
<button type="button" onclick="setAllStart(3, false);">-</button>
<div id="start-all" class="value">0</div>
<button type="button" onclick="setAllStart(3, true);">+</button>
</div>
<div>
AllEnd:
<button type="button" onclick="setAllEnd(3, false);">-</button>
<div id="end-all" class="value">10</div>
<button type="button" onclick="setAllEnd(3, true);">+</button>
</div>
<div>
Start 1:
<button type="button" onclick="setStart(1, false);">-</button>
<div id="start-1" class="value">3</div>
<button type="button" onclick="setStart(1, true);">+</button>
</div>
<div>
End 1:
<button type="button" onclick="setEnd(1, false);">-</button>
<div id="end-1" class="value">6</div>
<button type="button" onclick="setEnd(1, true);">+</button>
</div>
<div>
Start 2:
<button type="button" onclick="setStart(2, false);">-</button>
<div id="start-2" class="value">5</div>
<button type="button" onclick="setStart(2, true);">+</button>
</div>
<div>
End 2:
<button type="button" onclick="setEnd(2, false);">-</button>
<div id="end-2" class="value">8</div>
<button type="button" onclick="setEnd(2, true);">+</button>
</div>
<div>
Start 3:
<button type="button" onclick="setStart(3, false);">-</button>
<div id="start-3" class="value">2</div>
<button type="button" onclick="setStart(3, true);">+</button>
</div>
<div>
End 3:
<button type="button" onclick="setEnd(3, false);">-</button>
<div id="end-3" class="value">4</div>
<button type="button" onclick="setEnd(3, true);">+</button>
</div>
我的问题:
1) 我可以在 defineProperty 之后将我的属性的enumerable
更新为true
吗?
2) 如果在for-loop
中定义为obj.all =
而没有if-statement
,我可以跳过“不可枚举”键吗?
提前谢谢你。
【问题讨论】:
for...in
只“循环”通过枚举 - 不是吗?
是的。这就是为什么我将属性“all”定义为“nonenumerable”。
那么,有什么问题吗?为什么它需要“成为”可枚举的? obj.all
确实具有 helloworld!
的值 - 如果您使用 enumerable: true
创建它 - 不会追溯调用前一个循环
我更新了代码sn-p。我需要一个函数来一次更改所有值并自行更改每个值。这就是为什么用enumerable: false
定义obj.all
然后我需要将它存储在localStorage 中,以使用第二页上的数据。当我回到选择页面时,我还需要再次知道“all”的值。
【参考方案1】:
Object.defineProperty()
也可用于修改现有属性的描述符。对于您的用例,更好的方法是序列化原始对象的副本:
var open = ;
Object.assign(open, obj);
open.all = obj.all;
localStorage.setItem("localObj", JSON.stringify(open));
【讨论】:
感谢您的提示,我可以修改现有属性的描述符。不幸的是我不能使用对象的副本,因为我需要在加载对象时将对象与克隆合并。【参考方案2】:正如 ccprog 的回答中提到的,我可以使用 Object.defineProperty()
来修改我的对象属性。
var obj = ;
var name = "nonenumerable";
var value = "hello world";
Object.defineProperty(obj, name, value: value,
writable : true,
enumerable : false,
configurable : true
);
console.log(obj);
//output in code snippet console:
//output in browser console: nonenumerable: "hello world"
Object.defineProperty(obj, name,
enumerable : true
);
console.log(obj);
【讨论】:
【参考方案3】:辅助函数
function load(inp)
var spec = function (o)
Object.defineProperty(o, 'all',
writable: true,
enumerable: false,
configurable : true,
value: o.all ||
);
Object.defineProperty(o, "toString",
value: function ()
Object.defineProperty(this, 'all', enumerable: true);
var ret = JSON.stringify(this);
Object.defineProperty(this, 'all', enumerable: false);
return ret;
);
return o;
;
return spec(typeof inp == "string" ? JSON.parse(inp) : inp);
你可以像这样初始化对象
var obj = load(
1: id: 1, start: 3, end: 6 ,
2: id: 2, start: 5, end: 8 ,
3: id: 3, start: 2, end: 4
);
obj.all.start = 0;
obj.all.end = 10;
甚至像这样
var obj1 = load(
1: id: 1, start: 3, end: 6 ,
2: id: 2, start: 5, end: 8 ,
3: id: 3, start: 2, end: 4 ,
all:
start: 0,
end: 10
);
存储它
localStorage.setItem('testing', obj)
从存储中加载它
var obj2 = load(localStorage.getItem('testing'));
console.log(obj.toString() == obj2.toString());
// true
【讨论】:
这是一个非常好的解决方案,辅助函数非常好。我已经解决了这个问题,但这与我的解决方案非常相似。以上是关于如何更新对象属性的可枚举?的主要内容,如果未能解决你的问题,请参考以下文章
可枚举属性和不可枚举属性(for...in循环和Objec.keys()和Object.getOwnPropertyNames())