javascript将dotnotation字符串转换为对象

时间:2011-07-15 08:58:35

标签: javascript node.js

我有一个像客户端传递的"namespace.fun1.fun2.fun3"这样的字符串。它告诉服务器使用哪种功能。

如何安全地运行该功能?

现在我正在做:

var runthis = string.split('.')
namespace[runthis[1]][runthis[2]][runthis[3]]

如何安全地处理任意深度的嵌套?

6 个答案:

答案 0 :(得分:5)

我写的一个小功能。我在大多数应用程序中都使用它:

Object.lookup = (function _lookup() {
    var cache = { };

    return function _lookupClosure( lookup, failGracefully ) {
        var check   = null,
            chain   = [ ],
            lastkey = '';

        if( typeof lookup === 'string' ) {
            if( cache[ lookup ] ) {
                chain = cache[ lookup ].chain;
                check = cache[ lookup ].check;
            }
            else {
                lookup.split( /\./ ).forEach(function _forEach( key, index, arr ) {
                    if( check ) {
                        if( typeof check === 'object' ) {
                            if( key in check ) {
                                chain.push( check = check[ key ] );
                                lastkey = key;
                            }
                            else {
                                if( !failGracefully ) {
                                    throw new TypeError( 'cannot resolve "' + key + '" in ' + lastkey );    
                                }
                            }
                        }
                        else {
                            if( !failGracefully ) {
                                throw new TypeError( '"' + check + '" ' + ' does not seem to be an object' );   
                            }
                        }
                    }
                    else {
                        lastkey = key;
                        chain.push( check = window[ key ] );
                    }
                });

                if( check ) {
                    cache[ lookup ] = {
                        chain: chain,
                        check: check
                    };
                }
            }
        }

        return {
            execute: function _execute() {
                return typeof check === 'function' ? check.apply( chain[chain.length - 2], arguments ) : null;
            },
            get: function _get() {
                return check;
            }
        };
    }
}());

<强>用法:

Object.lookup( 'namespace.fun1.fun2.fun3' ).execute();

第一个参数是要解析的对象/方法/属性。第二个(可选)参数指示lookup()方法是否会以静默方式失败,或者如果某些属性或对象无法解析则抛出异常。默认是'throw'。为了避免这个电话

Object.lookup( 'namespace.fun1.fun2.fun3', true ).execute( 'with', 'paras' );

如果.fun3是一个函数,则可以将任何参数传递到.execute()。 如果您只想收到属性值,也可以拨打.get()而不是.execute()

var val = Object.lookup( 'namespace.fun1.fun2.fun3' ).get();

答案 1 :(得分:2)

(我可能会误解这个问题,但这就是我想到的)

var s = "space.f.g.h.i.j.k.l.m",
  a = s.split( "." ),
  fn = eval( a[0] );

for ( var i = 1; i < a.length; i++ ) {
  fn = fn[ a[i] ];
}

fn();

注意:这不会防止错误地或恶意地指定名称空间。

答案 2 :(得分:1)

这应该做:

var get = function(obj, key) {
  var s = key.split('.')
    , i = 1
    , l = s.length;

  for (; i < l; i++) {
    obj = obj[s[i]];
    if (!obj) return;
  }

  return obj;
};

get({hello:{world:{}}}, 'ns.hello.world');

编辑:稍微更改了代码

答案 3 :(得分:1)

这是一个简单的for循环,它应该从全局范围中找到指定strating的每个对象,然后运行它找到的函数。

window.namespace = { fun1: { fun2: { fun3: function() { alert('hi!') }}}};

runFunc = function(address) {
    var addressArray = address.split('.'),
        current = window,
        i = 0;

    for (i = 0; i < addressArray.length; i++) {
        current = current[addressArray[i]];
    }

    current();
};

runFunc('namespace.fun1.fun2.fun3');

http://jsfiddle.net/jfWra/1/

如果引用的值不存在或不是函数,那么这里会提供一些有意义的错误保护:http://jsfiddle.net/jfWra/2/

答案 4 :(得分:0)

这是使用递归函数的另一个简单解决方案:

function run(str, context) {
  var path = str.split(".")
  if path.length == 1 {
     context[path[0]].call()
     return;
  }

  if(typeof context == 'undefined') {
     context = window[path[0]]
  } else {
     context = context[path[0]]
  }
  run(path.splice(1).join('.'), context)
}

答案 5 :(得分:0)

两年后有这个模块:https://github.com/daaku/nodejs-dotaccess

var get = require("dotaccess").get;
var o = {a:{b:{c:'deep'}}};
console.log(get(o, 'a.b.c'));