JavaScript中使用getter與setter為什麼不好呢
如你所知,getter和setter已經成為了JavaScript的一部分。它們廣泛支援所有的主流瀏覽器,甚至是IE8。
我不認為這個點子通常是錯的,但我認為它不是非常適合JavaScript。可能看起來getter和setter可以簡化程式碼和節省時間,但其實它們會帶來隱藏錯誤,而這些錯誤第一眼看並不明顯。
getter和setter如何運作?
首先小小地總結一下這些是什麼東西:
有時候,我們希望能允許存取一個會返回動態計算值的屬性,或者你可能想要反映內部變數的狀態,而不使用顯式的方法呼叫。
為了說明它們是如何運作的,讓我們來看一個有著兩個屬性的person對象,這兩個屬性為:firstName和lastName,以及一個計算值:fullName。
var obj = { firstName: "Maks", lastName: "Nemisj" }
計算值fullName會傳回firstName和lastName兩者的串連。
Object.defineProperty(person, 'fullName', { get: function () { return this.firstName + ' ' + this.lastName; } });
為了得到fullName的計算值,不需要像person.fullName()帶可怕的括號,只需要使用簡單的var fullName = person.fullName。
這也適用於setter,你可以透過使用函數設定值:
Object.defineProperty(person, 'fullName', { set: function (value) { var names = value.split(' '); this.firstName = names[0]; this.lastName = names[1]; } });
使用就和getter一樣簡單:person.fullName = ‘Boris Gorbachev’。這將會呼叫上面定義的函數,並分離Boris Gorbachev成firstName和lastName。
問題在哪裡?
你也許在想:「嘿,我喜歡getter和setter方法,它們感覺更自然,就像JSON一樣。」你說得對,它們的確是這樣的,但我們先退一步來看一看fullName在getter和setter之前是如何運作的。
為得到值,我們將使用類似getFullName()的某些東西,以及為了設定值,我們將使用person.setFullName(‘Maks Nemisj’)。
如果拼錯函數名,person.getFullName()寫成person.getFulName()會發生什麼事?
JavaScript會給出一個錯誤:
person.getFulName(); ^ TypeError: undefined is not a function
這個錯誤會在適當的時候適當的地方被觸發。訪問函數不存在的物件將觸發錯誤——這是好的。
現在,讓我們來看看當用錯誤的名稱來使用setter的時候會發生什麼事?
person.fulName = 'Boris Gorbachev';
什麼都沒有。物件是可擴展的,可以動態分配鍵和值,因此不會有錯誤在運行時被拋出。
這樣的行為意味著錯誤可能顯示在使用者介面上的某個地方,或者,當某些操作被執行在錯誤的值上時,而並非是打字錯誤的時刻。
追蹤應該發生在過去但卻顯示在將來的程式碼流上的錯誤是如此有趣。
seal行不行
這個問題可以透過sealAPI來部分解決。只要物件是密封的,它就不能突變,也就是意味著fulName會試圖分配一個新鍵到person對象,而且它會失敗。
出於某種原因,當我在Node.js V4.0測試這個的時候,它沒有按照我期待的那樣工作。所以,我不能確保這個解決方案。
而更令人沮喪的是,對於setter一點也沒有解決方法。正如我前面提到的,物件是可擴展和可故障保護的,這意味著存取一個不存在的鍵不會導致任何錯誤。
如果這種情況只適用於物件的文字的話,我不會多此一舉地寫這篇文章,但在ECMAScript 2015(ES6)和用類別定義getter和setter能力的興起之後,我決定寫下關於潛在陷阱的部落格。
類別的到來
我知道目前類別在某些JavaScript社群中不是非常受歡迎。人們對在函數式/基於原型的語言,例如JavaScript中是否需要它們,爭執不休。然而,事實是,類別就在ECMAScript 2015(ES6)規範說明中,並且將存在於此一段時間。
對我來說,類別是指定在類別的外部世界(消費者)和應用程式的內部世界之間的定義良好的API的一種方式。這就是白紙黑字放入規則的抽象,我們假定這些規則不會很快改變。
改進person對象,做一個它的real類別。 person定義了介面用於取得和設定fullName。
class Person { constructor(firstName, lastName) { this.firstName = firstName; this.lastName = lastName; } getFullName() { return this.firstName + ' ' + this.lastName; } setFullName(value) { var names = value.split(' '); this.firstName = names[0]; this.lastName = names[1]; } }
類別定義了一個嚴格的介面描述,但getter和setter方法使其變得不太嚴格。我們已經習慣了臃腫的錯誤,當工作於物件文字和JSON時的按鍵中出現拼字錯誤的時候。我希望至少類別能夠更嚴格,並且在這個意義上,提供更好的回饋給開發人員。
雖然這種情況在定義getter和setter在一個類別上的時候沒有任何不同。但它不會阻止任何人拼錯。
class Person { constructor(firstName, lastName) { this.firstName = firstName; this.lastName = lastName; } get fullName() { return this.firstName + ' ' + this.lastName; } set fullName(value) { var names = value.split(' '); this.firstName = names[0]; this.lastName = names[1]; } }
有拼字錯誤的執行不會給出任何錯誤:
var person = new Person('Maks', 'Nemisj'); console.log(person.fulName);
同樣不嚴格,不冗長,不可追蹤的行為導致可能會出錯。
在我发现这一点后,我有一个问题:在使用getter和setter的时候,有没有什么可以做的,以便于使得类更严格?我发现:有是肯定有,但是这值得吗?增加额外层次的复杂性到代码就只是为了使用数量更少的括号?对于API定义,也可以不使用getter和setter,而这样一来就能解决这个问题。除非你是一个铁杆开发人员,并愿意继续进行,不然还有另一种解决方案,如下所述。
proxy来帮助?
除了getter和setter方法,ECMAScript 2015(ES6)还自带proxy对象。proxy可以帮助你确定委托方法,这些委托方法可以在实际访问键执行之前,用来执行各种操作。事实上,它看起来像动态getter / setter方法。
proxy对象可以用来捕捉任何到类的实例的访问,并且如果在类中没有找到预先定义的getter或setter就会抛出错误。
为了做到这一点,必须执行下面两个操作:
创建基于Person原型的getter和setter清单。
创建将测试这些清单的Proxy对象。
让我们来实现它。
首先,为了找出什么样的getter和setter方法可以用在类Person上,可以使用getOwnPropertyNames和getOwnPropertyDescriptor:
var names = Object.getOwnPropertyNames(Person.prototype); var getters = names.filter((name) => { var result = Object.getOwnPropertyDescriptor(Person.prototype, name); return !!result.get; }); var setters = names.filter((name) => { var result = Object.getOwnPropertyDescriptor(Person.prototype, name); return !!result.set; });
在此之后,创建一个Proxy对象:
var handler = { get(target, name) { if (getters.indexOf(name) != -1) { return target[name]; } throw new Error('Getter "' + name + '" not found in "Person"'); }, set(target, name) { if (setters.indexOf(name) != -1) { return target[name]; } throw new Error('Setter "' + name + '" not found in "Person"'); } }; person = new Proxy(person, handler);
现在,只要你尝试访问person.fulName,就会显示Error: Getter “fulName” not found in “Person”的消息。
以上是JavaScript中使用getter與setter為什麼不好呢的詳細內容。更多資訊請關注PHP中文網其他相關文章!

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

如何使用WebSocket和JavaScript實現線上語音辨識系統引言:隨著科技的不斷發展,語音辨識技術已成為了人工智慧領域的重要組成部分。而基於WebSocket和JavaScript實現的線上語音辨識系統,具備了低延遲、即時性和跨平台的特點,成為了廣泛應用的解決方案。本文將介紹如何使用WebSocket和JavaScript來實現線上語音辨識系

WebSocket與JavaScript:實現即時監控系統的關鍵技術引言:隨著互聯網技術的快速發展,即時監控系統在各個領域中得到了廣泛的應用。而實現即時監控的關鍵技術之一就是WebSocket與JavaScript的結合使用。本文將介紹WebSocket與JavaScript在即時監控系統中的應用,並給出程式碼範例,詳細解釋其實作原理。一、WebSocket技

如何利用JavaScript和WebSocket實現即時線上點餐系統介紹:隨著網路的普及和技術的進步,越來越多的餐廳開始提供線上點餐服務。為了實現即時線上點餐系統,我們可以利用JavaScript和WebSocket技術。 WebSocket是一種基於TCP協定的全雙工通訊協議,可實現客戶端與伺服器的即時雙向通訊。在即時線上點餐系統中,當使用者選擇菜餚並下訂單

如何使用WebSocket和JavaScript實現線上預約系統在當今數位化的時代,越來越多的業務和服務都需要提供線上預約功能。而實現一個高效、即時的線上預約系統是至關重要的。本文將介紹如何使用WebSocket和JavaScript來實作一個線上預約系統,並提供具體的程式碼範例。一、什麼是WebSocketWebSocket是一種在單一TCP連線上進行全雙工

JavaScript和WebSocket:打造高效的即時天氣預報系統引言:如今,天氣預報的準確性對於日常生活以及決策制定具有重要意義。隨著技術的發展,我們可以透過即時獲取天氣數據來提供更準確可靠的天氣預報。在本文中,我們將學習如何使用JavaScript和WebSocket技術,來建立一個高效的即時天氣預報系統。本文將透過具體的程式碼範例來展示實現的過程。 We

JavaScript教學:如何取得HTTP狀態碼,需要具體程式碼範例前言:在Web開發中,經常會涉及到與伺服器進行資料互動的場景。在與伺服器進行通訊時,我們經常需要取得傳回的HTTP狀態碼來判斷操作是否成功,並根據不同的狀態碼來進行對應的處理。本篇文章將教你如何使用JavaScript來取得HTTP狀態碼,並提供一些實用的程式碼範例。使用XMLHttpRequest

用法:在JavaScript中,insertBefore()方法用於在DOM樹中插入一個新的節點。這個方法需要兩個參數:要插入的新節點和參考節點(即新節點將要插入的位置的節點)。

JavaScript是一種廣泛應用於Web開發的程式語言,而WebSocket則是一種用於即時通訊的網路協定。結合二者的強大功能,我們可以打造一個高效率的即時影像處理系統。本文將介紹如何利用JavaScript和WebSocket來實作這個系統,並提供具體的程式碼範例。首先,我們需要明確指出即時影像處理系統的需求和目標。假設我們有一個攝影機設備,可以擷取即時的影像數
