2016-04-25 67 views
2

在通過網絡閱讀其他人的源代碼和各種文章時,我發現當不同的人在JavaScript中使用「面向對象風格」的編程時,他們通常會做得非常不同。JavaScript - 構建對象的不同方式

假設我想創建一個具有1個屬性和1個函數的小模塊。我已經看到至少4個方法,應付這一任務:

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

所有這些方法在語法上不同,但似乎產生可以以同樣的方式被使用的對象。

它們之間的語義差異是什麼?有什麼情況是因爲某種原因,我應該選擇其中一種方法來處理所有其他問題?

+1

選項2是沒有意義的,除非您在return語句之前添加更多代碼,可能會添加一些可從返回對象的方法中訪問的變量 - 否則它只是包含在冗餘IIFE中的選項1。選項1和2創建單例,而選項3和4爲您提供可用於創建多個實例的構造函數。而且你已經錯過了選項5,這將是3和4,但每個實例myProp設置,並在原型上設置myFunc()。 – nnnnnn

+0

可能的重複:[如何「正確」在JavaScript中創建自定義對象?](http://stackoverflow.com/questions/1595611/how-to-properly-create-a-custom-object-in-javascript) – Roberto

回答

3

myObject1是對象字面值(單例)。在你想只有一個這種類型的對象的情況下很有用。將它看作靜態對象。

myObject2返回對象文字。因此,在做了​​3210之後,變量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之間的區別在於,在前者的情況下,該對象的每個實例將有myPropmyFunc性能自己的副本,而後者只引用這些屬性。這意味着無論您創建多少個對象MyObject4,只會有一個myPropmyFunc

我建議您查看關閉,原型繼承和幾種對象設計模式(模塊等)在JavaScript中的工作方式。

2

1.和2.在你的例子中非常相似。你可以做2.使實際差異,宣佈在IIFE的範圍「私有」變量,就像這樣:

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

一般來說,那些創造,不是你會叫一個值。

相反,3.和4.正在做的是創建一個原型,然後可以用它來創建更多可用值。不管你是在原型還是在構造函數中實際聲明默認值,都沒有太大區別。因此,總而言之,就像一個「lambda」對象,沒有命名的原型,而實際上使得這個事物可重用和可重新使用。