构造函数 - 在简单命名空间中 - Javascript

Constructor function - in simple namespace - Javascript

想在命名空间内定义一个函数构造函数。到目前为止,我定义构造函数的方式是一个没有 NS 的简单构造函数,结合原型继承。

代码看起来有点像:

 function mySuperObject() {
    var self = this;
    self.p1 = "";
    self.p2 = "jkejie";
    // and others
    }
 mySuperObject.prototype.func1 = function(){...}
 // and others

引入命名空间:

在阅读了很多文章之后,我决定从一种非常简单的方式来定义命名空间开始,也许是最简单的方式。 基本上它只是定义一个指向对象文字的变量,内容是对象(上面代码片段中的 "mySuperObject" )。构造函数如下:mySuperObjectInNS.

对象代码:

var MYNAMESPACE = {

    //some variable outside the object
    file : "ConstructorInNamespace_obj.js: ",

    //Defining contructor function inside a namespace
    mySuperObjectInNS : function(propOne, propTwo){

        var self = this;
        self.objectName = "mySuperObject";
        self.propertyOne = propOne;
        self.propertyTwo = propTwo;

        self.doSomething = function(){
            console.log(file + " doSomething called - function of object");
        };

        ///many more functions and attributes
    }
}

MYNAMESPACE.mySuperObjectInNS.prototype.specialFunction = function(){
    console.log(file + " specialFunction called - prototypical inheritance defined in file of object, outside of namespace");
};

///many more functions and attributes

在另一个文件中可以实例化对象,如下所示:

...
var objOne = new MYNAMESPACE.mySuperObjectInNS("param11", "40");
//following line works just fine
objOne.doSomething();
 ....

问题:

It seems to me that this all is about defining an Object-Literal and I will come into trouble the latest I am trying to define "private" properties of that object. Is this correct?

"Private properties" 与使用对象进行命名空间无关。事实上,最初在回答这个问题时,我读作 "private functions" 因为 是相关的。

在JavaScript中有很多方法可以实现私有和半私有属性,但它们与您如何创建构造函数及其赋予对象的方法有关,而不是您如何公开构造函数. "Namespace" 对象是关于如何公开构造函数的。

创建 "private" 属性的一种常见模式是在 构造函数中定义需要访问它们的方法 ,并在其中创建 "properties" 局部变量构造函数(所以它们根本不是真正的属性),像这样:

function SuperObject() {
    var privateInformation;

    this.method = function() {
        // This can access `privateInformation`, which is completely
        // hidden from outside the constructor
    };
}

无论您是在 "namespacing" 模式中还是单独执行此操作都没有关系。

另一方面,

私有 函数 会影响模式。我将在下面展示两者。

提供私有函数的一个相当常见的变体是使用函数创建对象,这也使您有机会创建私有函数:

var TheNamespace = function() {
    function privateFunction() {
    }

    function SuperObject() {
        var privateInformation;

        this.method = function() {
            // This can access `privateInformation`, which is completely
            // hidden from outside the constructor
        };
    }

    SuperObject.prototype.otherMethod = function() {
        // Can't access `privateInformation`, but has the advantage
        // that the function is shared between instances
    };

    return {
        SuperObject: SuperObject
    };
}();

// usage
var s = new TheNamespace.SuperObject();

Is that mySuperObjectInNS still a constructor function? (For me it seems it is something else,even if I can intantiate objects from it.

是的。构造函数是任何希望您使用 new 的函数。

Is is a very bad very bad way of namespacing or is kind of ok?

使用对象作为伪命名空间是常见的做法。您还可以考虑各种 asynchronous module definition (AMD) 技术,这些技术在很大程度上使 "namespace" 对象变得不必要。


回复您的评论:

You defined a self-invoking function....which returns an an object?

它不是一个 self 调用函数,它是一个 inline 调用函数,但是,是的,它是一个 returns一个对象。

(if so I think parantheses are missing)

不,我们不需要任何不存在的括号,因为在您看到的其他地方使用外括号的唯一原因是告诉解析器单词 function 开始一个表达式而不是声明;我们在上面不需要它,因为我们已经在赋值的右侧,所以当遇到 function 时没有歧义。

Due to you proposed this way, is it a better way to define the ns?

"Better" 是一个主观术语。它为您提供了一个范围,您可以在其中定义您询问过的私有函数。

Whereas I often also saw the option: var = {} | someNSName; What is this all about?

如果您有多个文件会向 "namespace" 添加内容(这很常见),那么您经常会在每个文件中看到:

var TheNamespace = TheNamespace || {};

所做的是声明变量 if 它之前没有被声明过,并为它分配一个空对象 if 它还没有。在加载的 first 文件中,会发生这种情况:

  1. 处理 var 并创建一个新变量 TheNamespace,值为 undefined.

  2. 处理 TheNameSpace = TheNameSpace || {} 分配:由于 undefined 是假的,curiously-powerful || operator 导致新的 {},它被分配给 TheNamespace.

当加载 下一个 文件时,会发生这种情况:

  1. var是空操作,因为变量已经存在。

  2. 处理了TheNameSpace = TheNameSpace || {}赋值:因为TheNamespace有一个非null对象引用,它是真实的,而且奇怪的强大|| 运算符导致对 TheNamespace 所指对象的引用。

也就是完全没有作用

这样您就可以按任何顺序加载文件,或者单独加载一个文件。

这是一个例子:

thingy.js:

var TheNamespace = TheNamespace || {};
TheNamespace.Nifty = function() {
    function privateFunction() {
    }

    function Nifty() {
        var privateInformation;

        this.method = function() {
            // Can access `privateInformation` here
        };
    }

    Nifty.prototype.otherMethod = function() {
        // ...
    };

    return Nifty;
}();

thingy.js:

var TheNamespace = TheNamespace || {};
TheNamespace.Thingy = function() {
    function privateFunction() {
    }

    function Thingy() {
        var privateInformation;

        this.method = function() {
            // Can access `privateInformation` here
        };
    }

    Thingy.prototype.otherMethod = function() {
        // ...
    };

    return Thingy;
}();

该基本模式有 很多 变体,特别是如果一个文件可能向 TheNamespace 添加多个内容。这是一个相当简洁地支持这样做的人:

var TheNamespace = function(exports) {
    function privateFunction() {
    }

    function Nifty() {
        var privateInformation;

        this.method = function() {
            // Can access `privateInformation` here
        };
    }

    Nifty.prototype.otherMethod = function() {
        // ...
    };

    exports.Nifty = Nifty;

    function Thingy() {
        var privateInformation;

        this.method = function() {
            // Can access `privateInformation` here
        };
    }

    Thingy.prototype.otherMethod = function() {
        // ...
    };

    exports.Thingy = Thingy;
}(TheNamespace || {});