`
qbaty
  • 浏览: 96436 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

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

阅读更多
把函数做为命名空间已经是当今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
分享到:
评论

相关推荐

    python 类的私有变量和私有方法.docx

    若内部变量标示,如: 当使用“from M import”时,不会将以一个下划线开头的对象引入 。 2、 __xx 双下划线的表示的是私有类型的变量。只能允许这个类本身进行访问了,连子类也不可以用于命名一个类属性(类变量)...

    C++中静态成员函数与静态成员变量(static )

    (1)加在局部变量的前面使之成为静态局部变量,作用域还是在函数内部,可是生存周期延长了。 (2)加在全局变量的前面限定该变量作用域为文件作用域,就是说即使其他文件使用了extern扩展作用域也不行。这在C语言的...

    C++编程中的命名空间基本知识讲解

    命名空间是一个声明性区域,为其内部的标识符(类型、函数和变量等的名称)提供一个范围。命名空间用于将代码组织到逻辑组中,还可用于避免名称冲突,尤其是在基本代码包括多个库时。命名空间范围内的所有标识符彼此...

    C++文件组织

    又由于复合语句肯定是包含在函数内部(要么在主函数main()内,要么在自定义函数内),所以C语言中全局变量的定义“在所有函数之外”的说法同样适合C++。具有全局作用域的变量的作用域从定义位置起,到整个转换单元...

    Python语言基础:作用域.pptx

    作用域作用域作用域的查找顺序新作用域的引入目录Contents01作用域作用域作用域就是一个 Python 程序可以直接访问命名空间的正文区域。Python 中,变量的访问权限决定于这个变量是在哪里赋值的。变量的作用域决定了...

    python基础-函数详解

    文章目录python基础-函数详解一、什么是函数二、函数的作用三、定义函数四、函数的作用域和命名空间1.作用域(scope):变量生效的区域2.命名空间(namespace)五、调用函数1.函数递归:2.高阶函数:五、函数中的参数...

    API之网络函数---整理网络函数及功能

    LZInit 这个函数用于初始化内部缓冲区 LZOpenFile 该函数能执行大量不同的文件处理,而且兼容于压缩文件 LZRead 将数据从文件读入内存缓冲区 LZSeek 设置一个文件中进行读写的当前位置 MapViewOfFile 将一个文件...

    Python闭包之返回函数的函数用法示例

    闭包就是由其他函数动态生成并返回的函数,通俗地讲,在一个函数的内部,还有一个“内层”的函数,这个“内层”的函数是被返回的,它可以访问其创建者的局部命名空间中的变量。 下面是一个非常简单的例子: # ...

    谭浩强C语言程序设计,C++程序设计,严蔚敏数据结构,高一凡数据结构算法分析与实现.rar

    10.2.3 指针变量作为函数参数 137 10.2.4 指针变量几个问题的进一步说明 140 810.3 数组指针和指向数组的指针变量 141 10.3.1 指向数组元素的指针 142 10.3.2 通过指针引用数组元素 143 10.3.3 数组名作函数参数 146...

    谭浩强C语言程序设计,C++程序设计,严蔚敏数据结构,高一凡数据结构算法分析与实现.rar )

    10.2.3 指针变量作为函数参数 137 10.2.4 指针变量几个问题的进一步说明 140 810.3 数组指针和指向数组的指针变量 141 10.3.1 指向数组元素的指针 142 10.3.2 通过指针引用数组元素 143 10.3.3 数组名作函数参数 146...

    JS模块与命名空间的介绍

    起因将代码组织到类中的一个重要原因是让代码更加“模块化”,可以在很多不同的场景中实现代码的重用。但类不是唯一的模块化代码的方式。...实际上,可以将这个函数作用域用做模块的命名空间(模块函数) 一旦将模块

    精通WindowsAPI 函数 接口 编程实例

    11.2.1 创建命名管道 300 11.2.2 管道监听 302 11.2.3 使用异步I/O进行读写 303 11.2.4 关闭管道实例 307 11.2.5 客户端 307 11.3 剪贴板 310 11.3.1 获取、设置剪贴板数据 310 11.3.2 监视剪贴板 ...

    C++和面向对象数值计算

    第4章 命名空间和文件 4.1 命名空间 4.1.1 使用声明和指令 4.1.2 多重接口 4.1.3 命名空间别名 4.1.4 无名命名空间 4.1.5 名称查找 4.2 包含文件 4.2.1 包含标准库文件 4.2.2 用户自定义头...

    精通Windows.API-函数、接口、编程实例.pdf

    11.2.1 创建命名管道 300 11.2.2 管道监听 302 11.2.3 使用异步I/O进行读写 303 11.2.4 关闭管道实例 307 11.2.5 客户端 307 11.3 剪贴板 310 11.3.1 获取、设置剪贴板数据 310 11.3.2 监视剪贴板 ...

    Javascript闭包用法实例分析

    简而言之,就是能够读取其他函数内部变量的函数。 由于JS变量作用域的特性,外部不能访问内部变量,内部可以外部变量。 二、使用场景 1. 实现私有成员。 2. 保护命名空间,避免污染全局变量。 3. 缓存变量。 先看一...

    【C++】多文件程序结构.pdf

    具有内部链接性的: · 所有的声明 · 命名空间(包括全局命名空间)中的静态⾃由函数、静态友元函数、静态变量的定义、const常量定义 · enum定义 · inline函数定义(包括⾃由函数和⾮⾃由函数) · 类(class、struct...

    python09——函数2

    命名空间5. 递归函数 1. 函数的返回值 返回值就是函数执行以后返回的结果 通过return来指定函数的返回值 return后面可以跟任意对象,返回值甚至可以是一个函数 2. 文档字符串 help()是Python中内置函数,通过help()...

    element-constructors:关于如何为Element、HTMLElement等实现构造函数的一些想法

    元素的 localName 和命名空间决定了它的内部槽集。 new Foo的返回值以Foo.prototype作为原型。 其 (localName, namespace) 对与概念 (localName, namespace) → 构造函数注册表中的条目匹配的元素,除非作为其在...

Global site tag (gtag.js) - Google Analytics