嵌套javascript哈希的默认值

时间:2013-04-11 09:15:21

标签: javascript jquery hash prototypejs mootools

在JavaScript中,我想执行以下操作:

var pi = {}; pi[0]['*']['*'] = 1;

当然会抛出“无法读取属性'*'未定义”错误。显然我可以定义p [0] = {},但这有点痛苦,因为我将在不同的属性中粘贴许多不同的值,例如

pi[2]['O']['I-GENE'] = 1;

等。哈希的第一个键只是一个整数,所以我想我可以在顶层使用一个数组而不是一个哈希,然后默认初始化就像在这篇文章中一样:

default array values

但这并不能满足我对其他哈希值的默认初始化的需要。

看起来我想要做的就是遇到ECMAScript规范,它表明对象的未定义属性(这是JavaScript中的哈希)应该返回undefined,如下所述:

Set default value of javascript object attributes

有趣地包括危险的工作。

在我尝试使用这样的嵌套哈希的其他地方,我发现自己写了很多丑陋的代码,如下所示:

function incrementThreeGramCount(three_grams,category_minus_two,category_minus_one,category){
    if(three_grams[category_minus_two] === undefined){
      three_grams[category_minus_two] = {};
    }
    if(three_grams[category_minus_two][category_minus_one] === undefined){
      three_grams[category_minus_two][category_minus_one] = {};
    }
    if(three_grams[category_minus_two][category_minus_one][category] === undefined){
      three_grams[category_minus_two][category_minus_one][category] = 0;
    }
    three_grams[category_minus_two][category_minus_one][category]++;
}

我真的想在这里避免,或者至少找到一些通过原型方法添加Hash功能的好方法。然而,似乎因为JavaScript中的Hash和Object是同一个东西,我们不能真正使用JavaScript中的默认哈希行为而不影响很多其他事情......

也许我应该编写自己的Hash类......或者使用Prototypes:

http://prototypejs.org/doc/latest/language/Hash/

或其他人:

http://www.daveperrett.com/articles/2007/07/25/javascript-hash-class/

或mootools:

http://mootools.net/docs/more/Types/Hash

很多选择 - 希望我知道这里的最佳做法......

4 个答案:

答案 0 :(得分:2)

可以使用ES6 proxies完成此操作。您将使用get处理程序在对象上定义代理。对具有get值或对象没有自己的属性的键执行undefined时,将其设置为使用相同get处理程序的新代理并返回该新代理。

此外,这可以在不需要括号语法的情况下工作:

var obj = ...;
obj.a.b.c = 3;

不幸的是,作为ES6功能,他们的支持仅限于Firefox,并且可以在Chrome中启用实验标记。

答案 1 :(得分:1)

我会做那样的事情:

Object.prototype.get = function(v){ 
    if(!this[v]){
        this[v] = {} 
    } 

    return this[v];  
}

然后,object["x"]["y"].z = 666使用object.get("x").get("y").z = 666

答案 2 :(得分:0)

您可以编写一个简单的帮助程序来执行此操作。 e.g

function setWDef() {
    var args = [].slice.call(arguments);
    var obj = args.shift();
    var _obj = obj;
    var val = args.pop();
    if (typeof obj !== "object") throw new TypeError("Expected first argument to be of type object");
    for (var i = 0, j = args.length - 1; i < j; i++) {
        var curr = args[i];
        if (!_obj[curr]) _obj[curr] = {};
        _obj = _obj[curr];
    }
    _obj[args.pop()] = val;
    return obj;
}   

现在只需使用函数

设置值
var pi ={}
console.log (setWDef(pi,"0","*","a*",1)) //{"0": {"*": {"a*": 1}}}

继承人JSBin

上的演示

答案 3 :(得分:0)

使用 drafted logical OR assignment operator ||=,您可以执行以下操作:

 const pi = [];
 ((((pi[0]||={})['*'])||={})['*'] = 1);
 console.log(JSON.stringify({pi}));

输出:

{"pi":[{"*":{"*":1}}]}

您还可以将某些级别初始化为数组或定义默认属性值:

const pi = [];
((((((pi[0]||={})['*'])||=[])[3])||={'#':2})['*'] = 1);
console.log(JSON.stringify({pi}));

输出:

{"pi":[{"*":[null,null,null,{"#":2,"*":1}]}]}