`
qbaty
  • 浏览: 97041 次
  • 性别: 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系列」Python命名空间和作用域,命名空间(Namespace)和作用域(Scope)是两个非常重要的概念.md

    这些变量只能在该函数内部被访问,因此每个函数都可以有自己独立的局部命名空间,这对于防止变量之间的冲突非常有用。 - **内置命名空间**:这里的描述稍有重复,实际上“内置命名空间”已经是一种特定类型的命名...

    JavaScript 中的闭包是指内部函数可以访问外部函数作用域中的变量

    如果一个变量是在函数内部声明的,则该变量仅在该函数内可见;如果是在全局作用域中声明的,则该变量在整个程序中都可见。这种作用域规则确保了闭包能够在合适的情况下访问到正确的变量。 2. **函数作为值传递**:...

    js命名空间和闭包

    1. 对象字面量:这是一种创建命名空间的简单方式,通过创建一个对象并把相关的变量和函数作为该对象的属性。 ```javascript var MyNamespace = { var1: 'value1', function1: function() { ... } }; ``` 这样,`...

    第2章:VC程序设计基础——变量与函数

    变量的作用域有六种:块作用域、函数作用域、类作用域、命名空间作用域、文件作用域和程序作用域。块作用域的变量只在其定义的花括号内有效,如if或for语句中定义的变量。函数作用域的变量在函数内部有效,如形式...

    python 包、模块、函数与变量作用域视频讲解

    接下来是“包”(Package),它是管理Python模块命名空间的一种方式。一个包是一个含有__init__.py文件的文件夹,这个文件可以是空的,也可以包含初始化代码。包的作用是避免命名冲突,提供更好的代码组织结构。包内...

    Python进阶_关于命名空间与作用域(详解)

    例如,函数内部的变量和函数外部的变量存在于不同的命名空间中,互不影响。 1.2 **命名空间的种类** - **内置命名空间(Built-in Namespace)**:包含Python内置的函数和异常,如`abs()`、`TypeError`等。 - **...

    javascript自执行函数之伪命名空间封装法.docx

    这有助于避免全局作用域污染,同时也可以隐藏内部变量和函数,从而增强代码的安全性。 #### 三、伪命名空间 在JavaScript中,并没有像其他编程语言那样提供原生的命名空间支持。因此,开发者通常会使用对象字面量的...

    标准C++引入命名空间

    1. **显式限定访问**:使用命名空间的名字作为前缀来访问其中的成员。 ```cpp NamespaceName::i = 0; ``` 2. **使用作用域解析运算符**:在特定的作用域内使用命名空间的成员。 ```cpp void g() { Namespace...

    Python名称空间规则.docx#资源达人分享计划#

    例如,如果在函数内部定义了一个与全局变量同名的变量,那么在函数内部使用该变量时,实际上是在引用局部命名空间中的变量,而不是全局命名空间中的。 在实际编程中,合理利用名称空间可以提高代码的可读性和维护性...

    大的法师地方js命名空间

    函数内部通过将`name`字符串以`.`为分隔符进行拆分,得到一个数组`arr`,代表命名空间的层级。随后遍历这个数组,逐层检查当前层级的对象是否存在,如果不存在则创建一个空对象。这样,通过递归的方式,可以创建出...

    全局变量、局部变量、静态全局变量、静态局部变量的区别

    与全局变量相反,局部变量是在函数内部声明的变量,其作用域仅限于该函数内部。一旦函数执行完毕,局部变量就会被销毁,释放其所占用的内存空间。局部变量的生命周期与其所在函数的执行周期一致,函数调用时创建,...

    python中factor函数-Python基础教程.pdf

    - `vars()` 内置函数可以返回当前作用域(即命名空间)的字典,展示所有变量及其对应的值。 - 当在函数内部赋值时,如果没有使用 `global` 关键字,Python会默认创建一个局部变量,即使变量名与全局变量相同。 - ...

    14-namespaces(命名空间14).pdf

    通过命名空间,我们可以将相关功能组织在独立的文件或模块中,每个模块内部的命名空间都可以拥有自己的类型和变量,同时通过导出(`export`)来允许其他模块访问。 在实际应用中,当你需要为多个验证规则创建类时,...

    C 语言变量,函数重定义问题

    - 局部变量:只在定义它的函数内部可见。 - 全局变量:在整个源文件内可见。 - 外部变量:在其他源文件中定义但在当前文件中使用。 #### 三、头文件中的保护宏 在提供的示例代码中,可以看到头文件`test.h`使用...

    C语言函数调用过程中变量的同名问题的解决.pdf

    C语言函数调用过程中变量的同名问题的解决 在C语言函数调用过程中,变量的同名问题是一个常见...只有通过合理的变量命名、存储空间的分配和管理、复合语句的使用和内部变量和外部变量的管理,才能避免变量的同名问题。

    c++中有关命名空间(namespace)的一些介绍

    // 访问嵌套命名空间内的变量 } ``` 总的来说,C++的命名空间是一个强大的工具,用于管理和组织代码,避免命名冲突,提高代码的可读性和可维护性。合理使用命名空间,可以使大型项目变得更有条理,更容易理解和...

    利用命名空间来解决例程序名字冲突问题。

    它允许开发者在一个全局的作用域内定义多个独立的命名空间,每个命名空间内部可以包含各种类型的实体,如类、函数、变量等。通过这种方式,即使在不同的命名空间中有同名的实体,它们之间也不会发生冲突。 #### ...

    vs引入命名空间的快捷键.txt

    当你尝试访问一个未引入的命名空间下的类型时,VS会显示下划线或波浪线来标记错误。此时,只需按下`Ctrl + .`,就会出现一个列表,其中包含多个修复选项,选择“Add using statement”即可自动引入所需的命名空间。 ...

Global site tag (gtag.js) - Google Analytics