如何访问作为命名空间的函数内部变量

把函数做为命名空间已经是当今javascript编程里非常普遍的了。如果你把你的代码包含在一个函数里,那么你的代码里包含的变量和函数对于包含函数是本地的,或者说是局部的,这样则不会扰乱全局作用域。
var value = (function() {  // Wrapper function creates a local scope or namespace
    // your code goes here
    return value;  // Export a value from the namespace
})());  // Invoke the wrapper function to run your code


例如,现在假设你刚刚用XMLHttpRequest获得了一段字符串形式的javascript代码。你打算去执行这下代码,你可能会想要在一个命名空间里去执行这段代码,这样执行代码的过程中就不会产生全局的变量或是函数。
这很简单,只要在执行前把这段代码包含进一个函数里。在这个情况下,构造函数Function() 比起eval() 更加得心应手。

var code = ....;  // A string of JS code to evaluate
var f = new Function(code);   // Wrap it in a function
f();    // And run the function


这样做的一个问题是,函数创造出了一个密封的作用域,我们无法知道里面的值。
下面有一个我刚刚发现的方法。(我肯定肯定还有其他人也想到这种方法,但是我没有看到过任何其他地方出现,或是描述过这样的方法)在你包含你的代码前加上这一句:
return function(s) { return eval(s); };

现在,当你调用这个函数的时候,他将返回一个匿名函数。返回的函数在命名空间的作用域里执行了一个字符串。
所以你可以用他来探入命名空间,并且输出你想要的任何值!
如果你的代码字符串定义了一个你想用的构造函数名为Set(),你可以在一个命名空间里运行这些代码,然后像这样
从命名空间里提取

var code = readFile("Set.js");  // A string of JS code to evaluate
// Define and invoke a wrapper function with special suffix code.
// The return value is a namespace evaluator function and we treat
// it as a namespace object.
var setns = new Function(code + "return function(s) { return eval(s); };")(); 
var Set = setns("Set");  // Import the Set function from the namespace.
var s = new Set();  // Use the class we just imported


如果你有3个想从命名空间里提取出来

// Extract an object containing 3 values from the namespace
var sets = setns('{Set:"Set", BitSet:"BitSet", MultiSet:"MultiSet"}');
var bs = new sets.BitSet();



我已经定义了一个namespace()函数用来载入代码和自动生成这类命名空间。
/*
 * Load modules of code by enveloping them in a function and executing
 * the function: then they don't pollute the global namespace (unless they
 * assign to undeclared variables, but ES5 strict mode will prevent that.)
 * The wrapper function we create returns an evaluator function that 
 * evals a string inside the namespace. This evaluator function is the
 * return value of namespace() and provides read access to the symbols 
 * defined inside the namespace.
 */
function namespace(url) {
    if (!namespace.cache) namespace.cache = {};  // First call only
    if (!namespace.cache.hasOwnProperty(url)) {  // Only load urls once
        var code = gettext(url);           // Read code from url
        var f = new Function(code +        // Wrap code, add a return value
                             "return function(s) { return eval(s); };");
        namespace.cache[url] = f.call({}); // Invoke wrapper, cache evaluator
    }
    return namespace.cache[url];  // Return cached evaluator for this namespace
}
 
/* Return the text of the specified url, script element or file */
function gettext(url) {
    if (typeof XMLHttpRequest !== "undefined") { // Running in a browser
        if (url.charAt(0) == '#') {              // URL names a script tag
            var tag = document.getElementById(url.substring(1));
            if (!tag || tag.tagName != "SCRIPT")
                throw new Error("Unknown script " + url);
            if (tag.src) return gettext(tag.src);// If it has a src attribute
            else return tag.text;                // Otherwise use script content
        }
        else {                                   // Load file with Ajax
            var req = new XMLHttpRequest();
            req.open("GET", url, false);         // Asynchronous get
            req.send(null);
            return req.responseText;             // Error handling?
        }
    }
    else if (typeof readFile == "function") return readFile(url);  // Rhino
    else if (typeof snarf == "function") return snarf(url); // Spidermonkey
    else if (typeof read == "function") return read(url);   // V8
    else throw new Error("No mechanism to load module text");
}


你还可以找到这些函数在namespace.js里,我写了一个简单的demo,它并没有做什么有趣的事情,只是alert了一下256。
但如果你看看代码,你会发现他加载和为4个代码块生成了命名空间。
如果你是一个Python程序员你也许会想,这个技术可能可以用来补充python式的 “从A接向B” 类型模板系统,我一直在考虑和从事这类事情(但不准备共享代码)。
缺点,当然它没有办法去枚举并且进入所有你命名空间里定义的字符,所以我们无法模仿python的接口

翻译自: http://www.davidflanagan.com/2009/11/functions-as-na.html

你可能感兴趣的:(JavaScript,编程,Ajax,python,cache)