最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

node.js - javascript convert dotnotation string into objects - Stack Overflow

programmeradmin0浏览0评论

I have a string like this "namespace.fun1.fun2.fun3" passed from the client. It's telling the server which function to use.

How do I safely run the function?

right now i'm doing:

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

How do I handle arbitrary depth of nesting safely?

I have a string like this "namespace.fun1.fun2.fun3" passed from the client. It's telling the server which function to use.

How do I safely run the function?

right now i'm doing:

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

How do I handle arbitrary depth of nesting safely?

Share Improve this question asked Jul 15, 2011 at 8:58 HarryHarry 55k76 gold badges185 silver badges270 bronze badges
Add a ment  | 

6 Answers 6

Reset to default 5

A little function I wrote. I use it in most of my applications:

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;
            }
        };
    }
}());

usage:

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

The first parameter is the object/method/property to resolve. The second (optional) parameter indicates whether or not the lookup() method shall fail silently or throw an exception if some property or object could not get resolved. default is 'throw'. To avoid that call

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

If .fun3 is a function, you can pass in any parameters into .execute() instead. if you just want to receive the property value, you can also call .get() instead of .execute()

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

(I may be misinterpreting the question, but this is what came to mind)

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();

Note: this won't guard against the namespace being specified incorrectly or maliciously.

This should do:

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');

edit: changed code a bit

Here's a simple for loop that should do find each object specified strating from the global scope, and then run the function it finds.

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/jfWra/1/

And here's some eror protection that will throw something meaningful if the value referenced doesnt exist or is not a function: http://jsfiddle/jfWra/2/

Here's another simple solution using a recursive function:

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)
}

Two years later there is this module: https://github./daaku/nodejs-dotaccess.

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

评论列表(0)

  1. 暂无评论