JavaScript - Different ways to construct objects

时间:2016-04-25 09:03:24

标签: javascript oop module

While reading other people's source code and various articles over the web, I found that when different people use "object-oriented-style" programming in JavaScript, they often do it quite differently.

Suppose, I want to create a tiny module having 1 property and 1 function. I've seen at least 4 approaches to this task:

// Option 1
var myObject1 = {
    myProp: 1,
    myFunc: function () { alert("myProp has value " + this.myProp); }
};

// Option 2
var myObject2 = function () {
    return {
        myProp: 1,
        myFunc: function () { alert("myProp has value " + this.myProp); }
    };
}();

// Option 3
var MyObject3 = function () {
    this.myProp = 1;
    this.myFunc = function () { alert("myProp has value " + this.myProp); }
};
var myObject3 = new MyObject3();

// Option 4
var MyObject4 = function () { };
MyObject4.prototype.myProp = 1;
MyObject4.prototype.myFunc = function () { alert("myProp has value " + this.myProp); };
var myObject4 = new MyObject4();

All these approaches are syntactically different but seem to produce objects that can be used in the same way.

What's the semantic difference between them? Are there cases when for some reason I should choose one of these options over all the rest?

2 个答案:

答案 0 :(得分:3)

myObject1是一个对象文字(单身)。在您只想拥有此类型的一个对象的情况下很有用。将其视为静态对象。

myObject2 返回对象文字。因此,在var foo = myObject2()之后,变量foo将保留结果{ myProp: 1, myFunc: function(){...} },其中引用已执行的父函数。这称为闭包。例如,这可用于定义公共API或模块。

即:

var foo = (function(){
     var privateProp = "I am a private property";

     // the object below is returned, privateProp is accessible 
     // only through foo.publicProp
     return {
        publicProp: privateProp            
     }
})();

现在可以通过privateProp访问foo.publicProp媒体资源。

MyObject3MyObject4构造函数。通过在函数调用之前使用new关键字,您可以告诉JavaScript创建该对象的instance。这意味着以这种方式创建的每个新对象都将从对象定义继承属性和方法。

MyObject3MyObject4之间的区别在于前者的情况,该对象的每个实例都有自己的 myProp副本和myFunc属性,而后者仅引用这些属性。这意味着无论您创建的对象MyObject4的实例数是多少,都只有myPropmyFunc中的一个。

我建议您查看关闭,原型继承和几种对象设计模式(模块等)如何在JavaScript中工作。

答案 1 :(得分:2)

Both 1. and 2. are pretty much identical in your example. You could make 2. make an actual difference by declaring "private" variables in the IIFE's scope, like this:

var myObject2 = function () {
    var myPrivateProp = ...;
    return {
        getPrivateProp: function() { return myPrivateProp; }
    };
}();

In general, those create a value, not something that you would call a class of values.

Instead, what 3. and 4. are doing is creating a prototype that can be then used to create more usable values out of it. Whether you actually declare the defaults on the prototype or in the constructor doesn't make much difference.

So, to sum up, 1&2 are something like a "lambda" object, without a named prototype, while 3&4 actually make the thing reusable and recreatable.