好的,我正在尝试跟踪对web应用程序上的一个巨大表单所做的任何更改。加载页面时,我会创建一个JS对象,"捕获"所有输入字段(选择、单选按钮、复选框等)的初始状态。
当用户更改数百个输入元素中任何一个的值时,新值会在第二个对象中跟踪。当用户单击Update
时,将比较这两个对象,并且只发送那些已更改的值,以相应地更新数据。
与其构建两个完全独立的对象,我认为使用继承是明智的:
var initialState = getInitialState();//eg:{bar:'1',foo:'bar',atom:'bomb',some:{nested:'objects'}}
var tracker = Object.create(initialState);
随着事态的发展,tracker
对象可能最终看起来像这样:
{bar:'0',foo:'bar',atom:'peace',some:{nested:'objects'}}
当在FF和chrome中对此对象调用JSON.stringify
时,一切都很好:只返回对象自己的属性。IE中的情况并非如此:跟踪器没有prototype
属性,因此Object.create
会创建副本,而不是继承链tracker.__proto__ === initialState
返回true,而tracker.prototype === initialState
的计算结果为false,实际上tracker.prototype
属性未定义。
问题1:是否有另一种方法可以在IE中建立继承链,使我能够剥离未更改的原型值?
问题2:如果可能的话,我还想要一个方法来建立一个允许嵌套对象的继承链。现在,嵌套对象是通过使用递归函数迭代main对象来处理的。有点傻,因为这正是我想要省略的。
简而言之:
我想知道这是否存在:
var a = {bar:'1',foo:'bar',atom:'bomb',some:{nested:'objects'}};
var b = Object.magicDeepCreate(a);//<=== preferably X-browser
b.bar = '0';
b.bar.some.nested = 'stuff';
console.log(JSON.stringify(b));
//{"bar":"0","some":{"nested":"stuff"}}
一如既往:没有jQuery标签,意味着没有jQuery
注意:IE的意思是怪物IE8,而不是IE9(遗憾的是,公司政策)
tracker.__proto__ === initialState
返回true,而tracker.prototype === initialState
的计算结果为false,实际上tracker.prototype
属性是未定义的。
__proto__
属性是非标准的,仅限于FF。要获得对象的原型对象,请使用Object.getPrototypeOf()
。函数对象的prototype
属性是引用该函数的所有实例(使用new
创建)继承的对象的属性。
IE 中并非如此
在IE8中根本不支持Object.create()
。你是使用了通用垫片还是它无声地失败了?或者你甚至使用了一个真正复制所有属性的函数?
Object.magicDeepCreate(a)
,最好是X浏览器
这应该很简单,假设所有目标浏览器都实现Object.create
:
Object.deepCreate = function deepCreate(o) {
var res = Object.create(o);
for (var i in o)
if (Object.hasOwnProperty(o, i) && typeof o[i] == "object")
res[i] = deepCreate(o[i]);
return res;
};
仅字符串化那些已更改的
这应该是JSON.stringify
的标准行为——原型对象没有被考虑在内。
但是,我不知道为什么tracker
对象需要继承。只需使用一个空对象,然后添加所有已更改的属性。如果您想删除那些已重置为初始状态的对象,可以将其存储在一个额外的对象中进行比较,但没有继承的理由。只需使用:
Object.emptyStructure = function s(o){
var res = {};
for (var i in o)
if (typeof o[i] == "object")
res[i] = s(o[i]);
return res;
};
var initialState = getInitialState();
var tracker = Object.emptyStructure(initialState);
// set:
if (newVal == initialState.some.nested)
delete tracker.some.nested;
else
tracker.some.nested = newVal;