我有一个像客户端传递的"namespace.fun1.fun2.fun3"
这样的字符串。它告诉服务器使用哪种功能。
如何安全地运行该功能?
现在我正在做:
var runthis = string.split('.')
namespace[runthis[1]][runthis[2]][runthis[3]]
如何安全地处理任意深度的嵌套?
答案 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/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'));