【问题标题】:How can I create an empty namespace object without overwriting another object with the same name?如何在不覆盖另一个同名对象的情况下创建一个空的命名空间对象?
【发布时间】:2012-03-14 14:51:57
【问题描述】:

我一直在尽可能多地研究 Yahoo YUI 博客建议的模块模式。

我注意到 YUI 提供了创建一个新的空命名空间对象的能力,而无需像这样覆盖现有的同名对象:

YAHOO.namespace("myProject");

然后可以与YAHOO.myProject一起调用和使用

(提醒:如果YAHOO.myProject已经存在则不会被覆盖)

如何在不使用 YUI 的情况下使用纯 javascript 实现类似的效果?

请尽可能详细地解释。

可以在 here 找到完整的 YUI 博客文章。

随着我学习和加强我的 javascript 知识和技能,我正在尝试创建自己的个人 javascript 库(即使我从不需要使用它)

【问题讨论】:

    标签: javascript methods namespaces yui javascript-namespaces


    【解决方案1】:

    在您的示例中,它可以像这样工作:

    if (!YAHOO.myProject) {
        YAHOO.myProject = {};
    }
    YAHOO.myProject.whatever = true;
    

    或使用您自己的父模块名称:

    var myModule = myModule || {};  // make sure parent is defined without overwriting
    if (!myModule.myProject) {
        myModule.myProject = {};
    }
    myModule.myProject.whatever = true;
    

    或者定义自己的命名空间函数:

    function myNamespace(item) {
        if (!myModule[item]) {
            myModule[item] = {};
        }
    }
    
    myNamespace("myProject");
    myNamespace.myProject.whatever = true;
    

    【讨论】:

    • 好的,但是如果myModule.myProject 已经存在,您刚刚编写的代码不会阻止创建myProject 对象吗?
    • @Proud_to_be_Noob - 命名空间初始化的重点是如果它不存在就对其进行初始化,如果它确实存在则不管它。这就是这段代码的作用。您是否正在尝试做其他事情?
    • 我试图了解 YUI 人在使用他们的命名空间功能时会发生什么,因为他们的措辞暗示他们可以创建一个空的重复对象而不覆盖它。我也只是想找出一种很好的方法来基本上完成所显示的内容。 (我喜欢你刚刚发布的我自己的命名空间函数的定义,这有助于我理解很多 - 谢谢!)。
    • @Proud_to_be_Noob - 不。雅虎不会创建一个空的重复对象。他们只是做我上面描述的事情。如果它不存在,它们会对其进行初始化,如果它存在,则不理会它。你不能有两个同名的对象,你也不想这样。
    • 对,这就是我的想法,所以如果它已经存在,它只允许您使用已经存在的并在其上添加属性和方法,但不允许您更改原始的 myProject 对象那么对吗?
    【解决方案2】:

    编辑刚刚意识到我没有直接回答你的问题。对不起!不过希望这能帮助您了解一些替代技术。

    这是我不时使用的一种技术,例如当我想添加一次属性或函数并且不允许以后覆盖它时。

        var module = new function(){
    
            var modules = {}; //internal module cache
    
            return function(name, module){
                //return all modules
                if( !name ) return modules;
    
                //return specific module
                if( modules[name] ) return modules[name];
    
                //return the module and store it
                return modules[name] = module;
            }
    
        }
    

    所以你可以像这样使用它:

    //will store this since it doesn't exist
    module('test', 'foo'); //Since 'test' doesn't exist on the internal 'modules' variable, it sets this property with the value of 'foo'
    
    module('test'); // Since we aren't passing a 2nd parameter, it returns the value of 'test' on the internal 'modules' variable
    
    module('test', 'bar'); //We are attempting to change the value of 'test' to 'bar', but since 'test' already equals 'foo', it returns 'foo' instead.
    
    module(); // { 'test': 'foo' } //Here we aren't passing any parameters, so it just returns the entire internal 'modules' variable. 
    

    要看的关键是我们正在使用'new function()'。这是在赋值时完成的,因为我们真的希望“模块”成为内部函数,而不是外部函数。但是为了为内部的“var modules”变量创建一个闭包,外部函数必须在赋值时执行。

    还请注意,您也可以将外部函数编写为自执行:

    var module = function(){
        var modules = {};
        //other stuff
    }();
    

    【讨论】:

    • 您能否在第二部分中多放一些 cmets 来展示如何使用它。我理解第一部分,我只是想确保我理解第二部分。如果您在拥有的之外添加module('test2', 'foo2');,那么代码中会发生什么 - 在第二部分中?
    • 然后它将在内部模块对象上添加一个新属性,称为“test2”:“foo2”。基本上,它允许您设置一次属性,而以后无法更改它们。
    • 好的,我想我明白这一点,但我的意思是你能解释一下代码对每个module('test', 'foo'); module('test'); //'foo' module('test', 'bar'); //foo module(); // { 'test': 'foo' } 的反应以及它们各自的作用吗?
    • 如果您想获得一种行为,即保护属性在设置后不被更改,但在本机对象上,如 obj.prop = 1; obj.prop = 2; //保持 1,那么您必须使用并非所有浏览器都支持的 ES5 getter/setter。否则,您必须使用访问器函数对其进行模拟。
    • 添加了对正在发生的事情的更多解释。这有帮助吗?
    【解决方案3】:

    问。如何在不覆盖另一个同名对象的情况下创建一个空的命名空间对象?

    你不能。根据定义,同名不能同时引用新的空对象和现有对象。

    如果你的意思是“我怎样才能检查创建一个空的命名空间对象,如果它不存在,否则我想添加到现有的”,那么你只需这样做:

    if (!YAHOO.myProject)
       YAHOO.myProject = {};
    
    // or you may see this variation:
    YAHOO.myProject = YAHOO.myProject || {};
    

    我不喜欢后者,但经常使用它来达到与普通 if 语句相同的效果。

    要了解这个一般原则很多,请进一步查看这篇文章:http://www.adequatelygood.com/2010/3/JavaScript-Module-Pattern-In-Depth

    更新: 根据YUI API documentation for YAHOO.namespace(),方法“返回指定的命名空间,如果它不存在则创建它”——您会注意到,它比你正在阅读的博客,几乎支持了我已经说过的话......

    【讨论】:

    • 你刚才说的我都明白了,也正是我之前的想法,那为什么YAHOO YUI博客声称,“这分配了一个空对象myProject作为YAHOO的成员(但是如果 myProject 已经存在,则不会覆盖它)。现在我们可以开始向 YAHOO.myProject 添加成员了。” YUI 是否会以某种方式自动重新分配重复的 myProject 一个备用名称?
    猜你喜欢
    • 2016-11-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-13
    • 2013-11-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多