2013-06-19 58 views
5

這些不同的方法正確應用我更後端的傢伙比前端的傢伙,但JavaScript的令我着迷。我試圖將我的頭圍繞在我看來是多種不同的建模對象方法上。什麼是對象創建的JavaScript中

在過去的幾年裏,我一直主要在寫代碼,類似於這樣(假設jQuery是加載):

var TicketForm = { 

    elements: ['input', 'textarea', 'select', 'checkbox'], 

    enable: function(form) { 
     this.elements.forEach(function(el) { 
      form.find(el).prop('disabled', false); 
     }); 
    }, 

    disable: function(form) { 
     this.element.forEach(function(el) { 
      form.find(el).prop('disabled', true); 
     }); 
    } 
}; 

這樣我可以簡單地調用TicketForm.enable($('#whatever'));,使特定的形式,很類似於PHP中的靜態方法調用。

我一直在用PHP中的閉包玩,我意識到它們在JavaScript中也存在(我正在使用它們)。我試圖更徹底地把握這個概念。遇到這個驚人的腳本:http://codepen.io/stuffit/pen/KrAwx,我決定嘗試模仿該作者的編碼風格。只是試圖複製他的風格,我重寫我的代碼是這樣的:

var TicketForm = function() { 
    this.elements = ['input', 'textarea', 'select', 'checkbox']; 
}; 

TicketForm.prototype.enable = function(form) { 
    this.elements.forEach(function(el) { 
     form.find(el).prop('disabled', false); 
    }); 
}; 

TicketForm.prototype.disable = function(form) { 
    this.elements.forEach(function(el) { 
     form.find(el).prop('disabled', true); 
    }); 
}; 

然而,當我在這種情況下調用TicketForm.enable($('#whatever'));,我得到的錯誤

Uncaught TypeError: Object function() { 
    this.elements = ['input', 'textarea', 'select', 'checkbox']; 
} has no method 'enable' 

所以我做了一個小挖SO並發現How does JavaScript .prototype work?。第二個答案尤其是非常有啓發性,因爲我來自一個階級概念背景而不是原型概念背景。我還翻閱了一些幻燈片:http://ejohn.org/apps/learn/#65,這也很有幫助。事實證明,我所要做的就是創建TicketForm的一個實例,此時它的方法成爲提供給我:

var myForm = new TicketForm(); 
myForm.enable(form); // works as expected 

我有三個問題:

  1. 爲什麼,除了個人編碼風格,會選擇上述方法之一嗎?
  2. 爲什麼我必須用第二種方法聲明對象的一個​​實例,而我沒有第一個方法呢?
  3. 這些編碼風格是否有適當的名稱?
+0

http://www.amazon.com/JavaScript-Patterns-Stoyan-Stefanov/dp/0596806752/ – smk

+1

與您無關的實際問題,但只是說有時候,最好擴展jQuery而不是創建一個athor對象:http://jsfiddle.net/rMXRB/1/。執行'obj.method(選擇器)'你做'select.method()''。知道何時創建obj以及何時擴展對象是一件好事! –

回答

2

在JavaScript中,對象默認是可變的。這意味着除非您使用現代JavaScript引擎並且有人故意阻止對象被修改,否則您可以隨時添加,刪除和修改對象中的屬性。

在第一種情況下,你使用的是簡化的對象創建特殊的語法。語法{}創建一個簡單對象,該對象不超過Object的實例。這與在JS對象的可變性組合,指的是下述片段都是等效的:

var TicketForm = { 
    elements: ['input', 'textarea', 'select', 'checkbox'] 
}; 

var TicketForm = {}; 
TicketForm.elements = ['input', 'textarea', 'select', 'checkbox']; 

var TicketForm = new Object(); 
TicketForm.elements = ['input', 'textarea', 'select', 'checkbox']; 

基本上採用{}類似於經典的OOP語言創建一個對象的一個​​實例,同時創造一個構造函數是類似於使用一個類。在構造函數及其原型中,您可以定義一個藍圖,該構造函數的所有實例(共享該原型的所有對象)都將採用該藍圖。

所以這不是關於風格,而是關於你需要創建什麼。如果您需要同一事物的多個副本,則使用構造函數。如果你只需要一個,只需要創建一個普通的對象,不需要遵循禮節,做一個單身,並且一式三份地簽名;)

3

您的第一個方法定義了一個對象字面值,基本上創建了一個「singleton」。如果您需要同一個「類」的多個實例,則需要構造函數(或Object.create)。

+0

我相信這會回答你所有的3個問題,如果沒有,請告訴我。 – bfavaretto

+0

此外,也許這個我剛剛寫的其他答案可能會有所幫助:http://stackoverflow.com/questions/17200558/javascript-functions-and-objects-using-keyword-this-does-not-work – bfavaretto

+0

MDN頁面爲[ 'Object.create'](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create)。 –

0

第一種方法是「litteral object」,非常像靜態類,「這個「指的是父對象」TicketForm「,你可以將它理解爲」自我「。在第二種方法「這個」指的窗口,它不是面向對象的,除非你:

var myForm = new TicketForm(); 

這裏「這」指的是實例myForm的。此方法是「構造函數」方法(TicketForm是構造函數)