過載的 Getter Setter
2011 年 8 月 2 日
我最近在研究 JavaScript,其中一件事讓我印象深刻的是使用相同函式名稱作為 getter 和 setter 的習慣。因此,如果您想在 jQuery 中找出標題的高度,您會使用 $("#banner").height()
,而如果您想變更高度,您會使用 $("#banner").height(100)
。
這個慣例對我來說很熟悉,因為 Smalltalk 使用過它。您可以使用 banner height
取得值,並使用 banner height: 100
變更它。知道它是 Smalltalk 慣例就足以讓我喜歡它,因為我對那門語言有一種遙遠但持久的愛。但即使是最好的事物也有缺點,我無法隱藏我對這種編碼風格的不喜歡。
我的主要反對意見是,擷取資料的動作與設定值根本不同,因此名稱應該更明顯地不同。 [1]
另一個原因是 setter 和帶有參數的 getter 之間的混淆。如果我看到 $("#banner").css('height')
,一般預期是將 css 屬性設定為「height」。只有我對 jQuery API 的了解告訴我 css('height')
取得高度的值,而我會使用 css('height', 100)
更新它。
在 JavaScript 中,getter 和 setter 之間缺乏明確性比在 Smalltalk 中更大,因為只有一個方法。Smalltalk 是一種動態型別語言,但會根據方法的參數數量進行重載。[2] JavaScript 沒有在語言中進行重載,因此 getter 和 setter 會顯示為單一方法。文件可以提供幫助,但 API 本身並未區分它們。額外參數的存在會充當 FlagArgument,這通常是一件壞事。
我沒有建議 Java 醜陋的 getHeight()
/ setHeight(100)
慣例更好。我認為對 getter 使用裸值通常是最好的方法。我的偏好是讓任何 setter 都明顯突出。
一般來說,我喜歡透過不同的語法來做到這一點,因此 C# 和 Ruby 的屬性設定語法在此得分最高。在這些語言中,您可以使用 banner.height
取得值,並使用 banner.height = 100
變更它。此處的重點是使用賦值清楚地表示變異。您不會在 $("#banner").height(100)
和 $("#banner").css('height')
之間產生您遇到的歧義,因為您永遠不會在取得方法中使用 =
。
然而,這種方法確實依賴於支援它的語言。您無法使用 JavaScript 執行此操作 [3]。在這種情況下,我比較喜歡裸 getter 和前置 setter,因此您可以使用 banner.height()
取得值,並使用 banner.setHeight(100)
變更它。
儘管有此偏好,您仍必須遵循您所處理語言的慣例。如果我再次撰寫 Smalltalk,我仍會使用 height:100
以保持與語言慣例的一致性。然而,JavaScript 並不以有強烈的慣例而聞名,因此我寧願在此避免此慣例,即使 jQuery 使用它。
備註
1: 所謂的 getter 和 setter,我是指看起來會取得/設定值的函式,但可以透過任何方式實作,遵循 UniformAccessPrinciple。
2: 技術上來說,它不是超載,因為「height」和「height:」是不同的名稱(因為冒號)。但它確實感覺像是超載。
3: 自從我發布這篇文章後,有幾個人指出現在有一些 javascript property syntaxes,儘管它們尚未廣泛使用。