【问题标题】:Constructor function - in simple namespace - Javascript构造函数 - 在简单的命名空间 - Javascript
【发布时间】:2015-07-28 23:56:06
【问题描述】:

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

代码看起来有点像:

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

介绍命名空间:

在阅读了许多文章后,我决定从一种非常简单的方式来定义命名空间,也许是最简单的方式。 基本上,它只是定义一个指向对象文字的变量,内容是对象(上面的代码-sn-p 中的“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();
 ....

问题:

  • 在我看来,这一切都是关于定义一个 Object-Literal 和 我最近会遇到麻烦,我试图定义“私人” 该对象的属性。它是否正确?
  • 那 mySuperObjectInNS 还是构造函数吗? (对我来说 似乎它是别的东西,即使我可以从中实例化对象。
  • 命名空间是一种非常糟糕非常糟糕的方式还是还可以?

【问题讨论】:

    标签: javascript object namespaces prototype


    【解决方案1】:

    在我看来,这一切都是关于定义一个 Object-Literal 的,而我最近尝试定义该对象的“私有”属性时会遇到麻烦。这是正确的吗?

    “私有属性”与使用对象进行命名空间无关。事实上,最初在回答这个问题时,我将其解读为“私有函数”,因为这是相关的。

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

    创建“私有”属性的一种常见模式是定义需要访问它们的方法构造函数中,并在构造函数中创建“属性”局部变量(因此它们不是真正的属性),像这样:

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

    无论您是在“命名空间”模式中还是单独这样做,都没有关系。

    另一方面,私有函数会影响模式。我将在下面显示两者。

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

    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();
    

    那 mySuperObjectInNS 还是构造函数吗? (对我来说,这似乎是另一回事,即使我可以从中实例化对象。

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

    命名空间是一种非常糟糕非常糟糕的方式还是可以?

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


    你的评论:

    你定义了一个自调用函数......它返回一个对象?

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

    (如果是这样,我认为缺少括号)

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

    由于你提出了这种方式,是不是更好的方式来定义ns?

    “更好”是一个主观术语。它为您提供了一个范围,您可以在其中定义您所询问的私有函数。

    而我也经常看到这个选项:var = {} | someNSName; 这是怎么回事?

    如果您有多个文件可以将内容添加到“命名空间”(这很常见),那么您经常会在每个文件中看到这一点:

    var TheNamespace = TheNamespace || {};
    

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

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

    2. 处理TheNameSpace = TheNameSpace || {} 分配:由于undefined 是错误的,curiously-powerful || operator 会产生新的{},它被分配给TheNamespace.

    next 文件加载时,会发生这种情况:

    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 || {});
    

    【讨论】:

    • 你好克劳德。感谢您的良好回复,尽管我有一个问题:您定义了一个自调用函数(如果是这样,我认为括号丢失了),它返回一个对象?由于您提出了这种方式,这是定义ns的更好方法吗?由于这是一种常见的做法,我想我可以使用它。而我也经常看到这个选项:var = {} |一些NSName;这是怎么回事? (或者我应该发布一个额外的问题......?)
    • @Meru:我已添加到答案中以解决这些后续问题。
    • 非常感谢您的回答。而有一件事:与此同时,我尝试在对象文字中“创建”私有变量,我认为它成功了。我会将其发布为“答案”,否则难以描述。我希望这不违反这里的规则。Meru
    • 再一次是我。用函数表达式定义函数怎么样: var mysuperFunction = function () {....} ?
    • @Meru:在上面的上下文中,使用函数表达式(var mySuperFunction = function() { ... })或函数声明(function mySuperFunction() { ... })都没有关系。
    猜你喜欢
    • 1970-01-01
    • 2012-06-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-24
    • 2014-12-13
    • 2013-10-01
    相关资源
    最近更新 更多