2016-11-24 69 views
1
var x = {} 
x['hello'] = {"what": "world"} 
alert(x['hello'].what) 

因为显式设置元素'hello'而工作。如何设置尚未定义的元素的属性并实时创建它?

我想定义一个尚未未设置元素的proerty和动态创建它,像

var x = {} 
x['hello']['what'] = "world" 

这FAIS与TypeError: Cannot set property 'what' of undefined

有没有办法处理这种情况,类似于在Python中使用collections.defaultdict

+0

不,我不认为JavaScript有这个。 – Barmar

+0

古老的Perlish autovivification。不在Javascript中。但为什么你真的需要这个? – Thilo

+1

对单线队员的痴迷是什么?我们是否没有新行? – Barmar

回答

0

尝试使用Object.setPrototypeOf(x, {"what": "world"})。那对你有用吗?

或使用Object.setPrototypeOf({}, {"hello": {"what": "world"}})作为“hello”情况。

+0

。世界“}}),你可以尽可能深入你想要的。 –

+1

谢谢,但问题是它每次都会重新创建整个对象。换句话说,如果不覆盖第一项 – WoJ

+0

,如果(!myObject){//做我的事情},我就不能使用它两次。但是好的,我试过:) –

1

这有点粗糙,可能可以改进,但作为一个开始,你可以使用一个功能分裂一个。分隔字符串并为您创建嵌套的子对象。像这样的作品

function setObjValue(obj, nesting, value) { 
    var nestArr = Array.isArray(nesting) ? nesting : (nesting.indexOf(".") > -1) ? nesting.split(".") : [nesting], 
     len = nestArr.length,    
     i = 0, 
     cur = obj; 

    for (; i < len; i++) { 
    if (i === len-1) { 
     cur[nestArr[i]] = value; 
    } else { 
     if (!cur[nestArr[i]]) cur[nestArr[i]] = {}; 
     cur = cur[nestArr[i]]; 
    } 
    } 
} 

然后使用

var a = {}; 
setObjValue(a, "hello.what", "world"); 
//OR 
setObjValue(a, ["hello", "what"], "world"); 
console.log(a); //{hello:{ what: "world" }}; 

UPDATE: 我刚刚更新上面的功能和处理与已设置的键的对象小提琴,它也将接受嵌套参数作为数组。

JSFiddle

+0

嵌套可能是一个数组。 'setObjValue(a,[“hello”,“what”],“world”);' – Thilo

+1

Yup可以添加一个简单的检查并允许两种情况,内部字符串被拆分。无论如何,这将是非常简单的。主要向OP展示何去何从的想法。 –

0

您可以使用一个Proxy,但要注意的支持是不是全球。

还有一些必须考虑的边缘情况。下面是一个非常简单的(和潜在的天真)实施的JS defaultdict的:

function makeDefaultDictFor(obj) { 
 
    // Protect against infinite recursion for 
 
    // intentionally nonexistng properties 
 
    let bannedKeys = [Symbol.toPrimitive, Symbol.iterator, "toJSON"]; 
 
    
 
    // Create a proxy that returns a new object for any missing keys. 
 
    // The returned object also has the same behaviour, so you can 
 
    // nest infinitely deep. 
 
    return new Proxy(obj, { 
 
    get: (target, prop) => { 
 
     if (bannedKeys.indexOf(prop) >= 0) return; 
 
     
 
     // Return existing values when possible 
 
     if (prop in target) return target[prop]; 
 
     
 
     // Make a proxy like this one for undefined keys. 
 
     let newProxy = makeDefaultDictFor({}); 
 
     // Save the object as a property in this object. 
 
     target[prop] = newProxy; 
 
     
 
     return newProxy;  
 
    } 
 
    }); 
 
} 
 

 
let obj = makeDefaultDictFor({}); 
 
obj.hello.world = "!"; 
 
document.write("<pre>"); 
 
document.write(JSON.stringify(obj)); 
 
document.write("</pre>");

相关问题