2

我有一个变量obj定义如下:

{user: {username: "AzureDiamond", password: "hunter2"}}

我有一个str可能被定义为以下任何字符串的字符串:

  • “用户”
  • “用户[用户名]”
  • “用户密码]”
  • “伪造的”

我在 JS(特别是 node.js)中是否有一种相对简单的方法可以基本上/动态地执行以下操作?

  • str == "user",返回{username: "AzureDiamon", password: "hunter2"}
  • str == "user[username]",返回“AzureDiamond”
  • str == "user[password]",返回“hunter2”
  • str == "fake",返回null

编辑:这个问题更多是为了找出除了正则表达式匹配之外我可以使用的更简单或内置到 JS/node.js 中的东西。

4

3 回答 3

4

解决方案

如果您确定 的语法str正确,则该函数可能如下所示:

function get_by_path(source, path){
    var path_elements = path.split(']').join('').split('[');
    for (var i=0; i < path_elements.length; i++){
        source = source[path_elements[i]];
        if (typeof source === 'undefined'){
            return null;
        }
    };
    return source;
};

测试

这是它的行为方式:

var data = {'user': {
    'username': "AzureDiamond", 'password': "hunter2",
    'details': {'address': {'street': "Happiness Street"}}
}};

get_by_path(data, 'user');                           // gives user object
get_by_path(data, 'user[username]');                 // gives "hunter2"
get_by_path(data, 'user[password]');                 // gives "AzureDiamond"
get_by_path(data, 'fake');                           // gives null
get_by_path(data, 'user[details][address][street]'); // gives "Happiness Street"

解释

该脚本不使用正则表达式,也不使用危险eval()的调用,只假设您的“路径”将以一个不带括号的单词开头,并且每个下一部分(如果有)将是括在方括号中的单词。如果在遍历的对象中找不到某些路径,null则将返回。如果它被找到,它将被返回(不管它是一些复杂的对象、字符串null、、布尔值还是其他任何东西)。

脚本从解析您的路径开始。它通过删除右方括号 (" ]") 并通过打开方括号 (" [") 拆分结果字符串来做到这一点。该过程如下所示:

"user"                  -> "user"                -> ["user"]
"user[username]"        -> "user[username"       -> ["user", "username"]
"user[password]"        -> "user[password"       -> ["user", "password"]
"user[address][street]" -> "user[address[street" -> ["user", "address", "street"]
"fake"                  -> "fake"                -> ["fake"]

因此,如您所见,最后您有一个路径元素数组。这些被一一评估。如果在任何级别上都无法对数据参数的结构进行更深入的适当步骤,则null返回。否则返回最后访问的元素。

证明

它有效的证明在这里:http: //jsfiddle.net/EJCgE/2/

编辑replace():由于字符串方法的工作原理,更复杂的路径(当有两个以上级别时)存在一些问题。我已更新我的代码以不包含 jQuery 并修复该问题。

EDIT2:我已更新脚本以删除冗余行和一个冗余变量。

于 2012-06-16T02:41:49.590 回答
2

这直接取自 EXTJS3 源代码,但我已经多次使用它来做类似的事情。

createAccessor : function(){
    var re = /[\[\.]/;
    return function(expr) {
        if(Ext.isEmpty(expr)){
            return Ext.emptyFn;
        }
        if(Ext.isFunction(expr)){
            return expr;
        }
        var i = String(expr).search(re);
        if(i >= 0){
            return new Function('obj', 'return obj' + (i > 0 ? '.' : '') + expr);
        }
        return function(obj){
            return obj[expr];
        };

    };
}(),

你会这样使用它:

var accessor = createAccessor(str);
var data = accessor(object);
于 2012-06-16T02:28:07.753 回答
0

试试这个eval功能。它接受一个字符串,并像执行 javascript 代码一样执行该字符串。例如:

var data = {user: {username: "AzureDiamond", password: "hunter2"}};
var str = "user[\"password\"]";
console.log( eval("data." + str) );
// Prints "hunter2"

但是你必须非常小心,因为根据它的str来源,人们基本上可以在你的服务器上远程运行代码。在执行之前使用正则表达式验证字符串,以确保人们无法向您发送偷偷摸摸的信息并将您的服务器破解为位。

编辑:请注意,您还必须引用password,以便在执行时将其视为字符串,而不是变量。

于 2012-06-16T02:25:19.407 回答