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

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

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


当前回答

JavaScript还没有命名空间的原生表示,但TypeScript有。

例如,您可以使用以下TS代码(playground)

namespace Stack {
    export const hello = () => console.log('hi')
}

Stack.hello()

如果你不能将你的代码更新到TS,你至少可以使用TS在为命名空间生成JS输出时所采用的模式,它看起来像这样:

var Stack;
(function (Stack) {
    Stack.hello = () => console.log('hi');
})(Stack || (Stack = {}));
Stack.hello();

进一步阅读:

TS -命名空间 命名空间和模块

其他回答

我最近最喜欢的图案是这样的:

Var命名空间=(函数(){ //暴露给公众 返回{ internalA, c: internalC } //所有私有 /** *完整的JSDoc * / 函数internalA() { / /…… } /** *完整的JSDoc * / 函数internalB() { / /…… } /** *完整的JSDoc * / 函数internalC() { / /…… } /** *完整的JSDoc * / 函数internalD() { / /…… } }) ();

当然,return可以在后面,但是如果后面只有函数声明,那么就更容易看到名称空间是关于什么的,以及暴露了什么API。

在这种情况下使用函数表达式的模式导致不遍历整个代码就无法知道公开了哪些方法。

下面是Stoyan Stefanov在他的JavaScript Patterns一书中是如何做到这一点的,我发现这本书非常好(它还展示了他如何做注释,允许自动生成API文档,以及如何向自定义对象的原型添加一个方法):

/**
* My JavaScript application
*
* @module myapp
*/

/** @namespace Namespace for MYAPP classes and functions. */
var MYAPP = MYAPP || {};

/**
* A maths utility
* @namespace MYAPP
* @class math_stuff
*/
MYAPP.math_stuff = {

    /**
    * Sums two numbers
    *
    * @method sum
    * @param {Number} a First number
    * @param {Number} b Second number
    * @return {Number} Sum of the inputs
    */
    sum: function (a, b) {
        return a + b;
    },

    /**
    * Multiplies two numbers
    *
    * @method multi
    * @param {Number} a First number
    * @param {Number} b Second number
    * @return {Number} The inputs multiplied
    */
    multi: function (a, b) {
        return a * b;
    }
};

/**
* Constructs Person objects
* @class Person
* @constructor
* @namespace MYAPP
* @param {String} First name
* @param {String} Last name
*/
MYAPP.Person = function (first, last) {

    /**
    * First name of the Person
    * @property first_name
    * @type String
    */
    this.first_name = first;

    /**
    * Last name of the Person
    * @property last_name
    * @type String
    */
    this.last_name = last;
};

/**
* Return Person's full name
*
* @method getName
* @return {String} First name + last name
*/
MYAPP.Person.prototype.getName = function () {
    return this.first_name + ' ' + this.last_name;
};

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

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!";

JavaScript还没有命名空间的原生表示,但TypeScript有。

例如,您可以使用以下TS代码(playground)

namespace Stack {
    export const hello = () => console.log('hi')
}

Stack.hello()

如果你不能将你的代码更新到TS,你至少可以使用TS在为命名空间生成JS输出时所采用的模式,它看起来像这样:

var Stack;
(function (Stack) {
    Stack.hello = () => console.log('hi');
})(Stack || (Stack = {}));
Stack.hello();

进一步阅读:

TS -命名空间 命名空间和模块

我喜欢这个:

var yourNamespace = {

    foo: function() {
    },

    bar: function() {
    }
};

...

yourNamespace.foo();