-1

例如,如果我有这样的事情:

var Constants = {
  scope:{
    namespaceA: { A_X: "TEST_AX" , A_Y: "TEST_AY" },
    namespaceN: { N_X: "TEST_NX" , N_Y: "TEST_NY" }
  }
  _mapping: [],
  getMapping: function(){...}
}

var flattenList = flatten(Constants.scope); //returns ["TEST_AX","TEST_AY","TEST_NX","TEST_NY"]
var anotherWayFlattened = flatten(Constants.scope.namespaceA,Constants.scope.namespaceB); //returns same result as above

编辑:一种方法是通过 for-each 循环遍历范围,但我正在寻找更优雅的东西?

双重编辑:好的,我刚刚做了这样的事情:

var flattenedList = (function(list){
    var flatList = []
    $.each(list,function(i,items){
        for(var p in items) flatList.push(items[p]);
    })
    return flatList;
})([Constants.scope.namespaceA,Constants.scope.namespaceB]);

但想知道我们是否可以避免传入特定属性而只传入常量并搜索命名空间列表

4

3 回答 3

1

[Constants.scope.namespaceA,Constants.scope.namespaceB]

我想知道为什么您在数组中显式传递子对象。为什么不直接传递整个Constants.scope对象?

var flattenedList = (function(obj){
    var flatList = []
    for (var prop in obj) {
        var items = obj[prop];
        for (var p in items)
            flatList.push(items[p]);
    }
    return flatList;
})(Constants.scope);

从您的评论看来,您想要这个:

var flattenedList = (function(obj, test){
    var flatList = []
    for (var prop in obj) {
        if (!test(prop))
            continue;
        var items = obj[prop];
        for (var p in items)
            flatList.push(items[p]);
    }
    return flatList;
})(Constants, function(name) {
    return name.substr(0, 9) == "namespace";
    // or maybe
    return /^namespace[A-Z]$/.test(name);
});
于 2013-02-13T19:46:30.090 回答
1

如果你想递归到任何(非周期性!)深度,你可以这样做:

function flattenList(list, accumulator){
    accumulator = accumulator || [];
    for(var p in list){
        if(list.hasOwnProperty(p)) {
            if(typeof list[p] === "string") {
                accumulator.push(list[p]);
            } else if(typeof list[p] === "object") { // this is not a reliable test!
                flattenList(list[p], accumulator);
            }
        }
    }
    return accumulator;
}

这段代码做了许多假设——我们的对象末尾只有字符串等。或者,如果您事先知道深度,您当前的解决方案可以使用 concat 进行优化:

var flattenedList = (function(list){
    return Array.prototype.concat.apply([], list);
})([Constants.scope.namespaceA,Constants.scope.namespaceB]);
于 2013-02-13T19:56:22.210 回答
1

这是一种允许更深嵌套的方法。我知道这不是目标的一部分,但我发现这是一个更有趣的问题。:-)

var flatten = (function() {
    var toString = Object.prototype.toString, slice = Array.prototype.slice;
    var flatten = function(input, output) {
        var value;
        output = (toString.call(output) == "[object Array]") ? output : [];
        for (name in input) {if (input.hasOwnProperty(name)) {
            value = input[name];
            if (toString.call(value) == "[object Object]") {
                flatten(value, output);
            } else {
                output.push(value);
            }
        }};
        return output;
    };
    var merge = function(first, second) {
        return first.concat(second);
    }

    return function() {
        return slice.call(arguments).map(flatten).reduce(merge);
    };
}());

这允许任何一种方法:

flatten(Constants.scope);
flatten(Constants.scope.namespaceA, Constants.scope.namespaceN);

你可以传入任意多个单独的参数,或者一个参数。他们都会被搜索到任意深度。

对于某些环境,您可能需要填充Array.prototype函数mapreduce.

于 2013-02-13T20:47:41.137 回答