如何在JavaScript中创建命名空间,使我的对象和函数不被其他同名对象和函数覆盖?我使用了以下方法:

if (Foo == null || typeof(Foo) != "object") { var Foo = new Object();}

有没有更优雅或更简洁的方式来做到这一点?


当前回答

我喜欢Jaco Pretorius的解决方案,但我想通过将“this”关键字指向模块/名称空间对象来使其更有用。 我的煎锅版本:

(function ($, undefined) {

    console.log(this);

}).call(window.myNamespace = window.myNamespace || {}, jQuery);

其他回答

ES6 Modules命名空间导入

// circle.js
export { name, draw, reportArea, reportPerimeter };
// main.js
import * as Circle from './modules/circle.js';

// draw a circle
let circle1 = Circle.draw(myCanvas.ctx, 75, 200, 100, 'green');
Circle.reportArea(circle1.radius, reportList);
Circle.reportPerimeter(circle1.radius, reportList);

这将获取Circle .js中所有可用的导出,并使它们作为对象Circle的成员可用,有效地为其提供了自己的名称空间。

我写了另一个命名空间库,它的工作方式有点像其他语言中的包/单元。它允许你创建一个JavaScript代码包,并从其他代码中引用这个包:

文件hello.js

Package("hello", [], function() {
  function greeting() {
    alert("Hello World!");
  }
  // Expose function greeting to other packages
  Export("greeting", greeting);
});

文件Example.js

Package("example", ["hello"], function(greeting) {
  // Greeting is available here
  greeting();  // Alerts: "Hello World!"
});

页面中只需要包含第二个文件。它的依赖项(本例中的文件hello.js)将自动加载,从这些依赖项导出的对象将用于填充回调函数的参数。

你可以在Packages JS中找到相关的项目。

您可以声明一个简单的函数来提供名称空间。

function namespace(namespace) {
    var object = this, tokens = namespace.split("."), token;

    while (tokens.length > 0) {
        token = tokens.shift();

        if (typeof object[token] === "undefined") {
            object[token] = {};
        }

        object = object[token];
    }

    return object;
}

// Usage example
namespace("foo.bar").baz = "I'm a value!";

虽然我已经晚了7年,但是在8年前我已经为此做了很多工作:

http://blogger.ziesemer.com/2008/05/javascript-namespace-function.html http://blogger.ziesemer.com/2007/10/respecting-javascript-global-namespace.html

能够轻松有效地创建多个嵌套的名称空间,以保持复杂的web应用程序的组织和管理,同时尊重JavaScript全局名称空间(防止名称空间污染),并且在这样做的时候不破坏名称空间路径中的任何现有对象,这是很重要的。

以上是我在2008年前后的解决方案:

var namespace = function(name, separator, container){
  var ns = name.split(separator || '.'),
    o = container || window,
    i,
    len;
  for(i = 0, len = ns.length; i < len; i++){
    o = o[ns[i]] = o[ns[i]] || {};
  }
  return o;
};

这不是创建名称空间,而是提供了创建名称空间的函数。

这可以浓缩成一个简化的一行代码:

var namespace=function(c,f,b){var e=c.split(f||"."),g=b||window,d,a;for(d=0,a=e.length;d<a;d++){g=g[e[d]]=g[e[d]]||{}}return g};

使用示例:

namespace("com.example.namespace");
com.example.namespace.test = function(){
  alert("In namespaced function.");
};

或者,作为一种说法:

namespace("com.example.namespace").test = function(){
  alert("In namespaced function.");
};

然后执行如下:

com.example.namespace.test();

如果你不需要支持旧浏览器,更新版本:

const namespace = function(name, separator, container){
    var o = container || window;
    name.split(separator || '.').forEach(function(x){
        o = o[x] = o[x] || {};
    });
    return o;
};

现在,我对将命名空间暴露给全局命名空间本身持谨慎态度。(可惜基础语言没有为我们提供这个!)所以我通常会在闭包中使用这个,比如:

(函数(){ Const namespace = function(名称,分隔符,容器){ Var o =容器||窗口; 的名字。split(separator || '.'). foreach(函数(x){ O = O [x] = O [x] || {}; }); 返回啊; }; const ns = namespace("com.ziesemer.myApp"); / /可选: ns.namespace = ns; //进一步扩展,使用ns从这里… } ()); console.log (\ com \”:“com);

在较大的应用程序中,这只需要在页面加载开始时定义一次(对于基于客户端的web应用程序)。如果保留的话,其他文件可以重用命名空间函数(在上面包含为“可选”)。在最坏的情况下,如果这个函数被重新声明了几次——它只需要几行代码,如果简化了,就会更少。

这是Ionuț G. Stan的回答的后续,但通过使用var ClassFirst = this显示了整洁代码的好处。ClassFirst = function(){…},它利用JavaScript的闭包作用域来减少相同名称空间中的类的名称空间混乱。

var Namespace = new function() {
    var ClassFirst = this.ClassFirst = function() {
        this.abc = 123;
    }

    var ClassSecond = this.ClassSecond = function() {
        console.log("Cluttered way to access another class in namespace: ", new Namespace.ClassFirst().abc);
        console.log("Nicer way to access a class in same namespace: ", new ClassFirst().abc);
    }
}

var Namespace2 = new function() {
    var ClassFirst = this.ClassFirst = function() {
        this.abc = 666;
    }

    var ClassSecond = this.ClassSecond = function() {
        console.log("Cluttered way to access another class in namespace: ", new Namespace2.ClassFirst().abc);
        console.log("Nicer way to access a class in same namespace: ", new ClassFirst().abc);
    }
}

new Namespace.ClassSecond()
new Namespace2.ClassSecond()

输出:

Cluttered way to access another class in namespace: 123
Nicer way to access a class in same namespace: 123
Cluttered way to access another class in namespace: 666
Nicer way to access a class in same namespace: 666