簡體   English   中英

JavaScript 中是否需要 `getter` 和 `setter`?

[英]Are `getter` and `setter` necessary in JavaScript?

class Employee {

    constructor(name, age) {
        this._name = name;
        this.age = age;
    }

    doWork() {
        return `${this._name} is working`;
    }

    get name() {
        return this._name.toUpperCase();
    }

    set name(newName){
        if(newName){ 
            this._name = newName;
        }
    }
}

let man = new Employee('A', 10);
console.log(man.name, man.age);
man.name = 'B';
man.age = 20;
console.log(man.name, man.age);

這是我的代碼。 我為_name成員創建了一個gettersetter 我沒有為age創建gettersetter

但是兩者都可以像這樣更新這兩個字段man.name = 'B';man.age = 20;

所以我很困惑,JavaScript 中是否需要gettersetter

是的,getter或setter有時非常有用,但只需要在需要特定功能時使用它們 - 否則沒有getter或setter的普通屬性訪問就可以了。

如果要在每次請求屬性時運行某些代碼,則可以使用getter。 在您的示例中,無論名稱是什么,getter始終返回名稱的大寫版本,同時保留實際案例以供內部使用。

如果要在每次設置屬性時運行某些代碼,則可以使用setter。 在您的情況下,它會阻止設置假名稱。 沒有getter / setter,您無法實現這些功能。

當您不需要getter或setter特殊邏輯時,直接屬性訪問是一種非常好的方法。

getter和setter也可能獲取並設置一些不公開的屬性(因此通過正常的屬性訪問根本不可用),因為它存儲在某個地方(不是作為此對象的屬性)或私有存儲或即使它存儲在其他地方,例如某些硬件設備中。 在這些情況下,getter和setter會模擬實際不存在的屬性值。 因此,它們簡化了界面,同時允許從任何地方存儲或檢索實際值。

必要? 沒有。

是否有最佳表達為getter / setter的場景? 是。 考慮“計算屬性”:

//declare an object
rectangle = {
   x: 10,
   y: 20,
   get area() { return this.x * this.y }  //won't occupy storage
}

//usage
log('the area is', rectangle.area)        //=> 'the area is 200'.
                                          //   cleaner syntax (no parentheses)

考慮API設計人員的需求 - 他們很可能對用戶如何看待他們的API過於敏感。 每一位(或在這種情況下,括號)都計入清理界面。

是的,他們是非常必要的。 只是不是每個財產。

以下是設置者的兩個理由:

1.您需要驗證傳入的值。

假設您的值必須是0到100之間的整數。您的setter可以驗證傳入值的類型是否正確並且在正確的范圍內:

 class Range { set value(newVal) { let val = Number(newVal); if( newVal == null || typeof newVal === 'string' || !Number.isInteger(val) || val < 0 || val > 100 ) { const err = `'value' must be an integer from 0 to 100 and not ${newVal}`; console.error(err); //throw new TypeError(err); } // save newVal } } const x = new Range(); x.value = 200; x.value = 10; x.value = "10"; x.value = new Number(22); 

2.每次價值變化時你都需要做點什么

 class ValOutput { constructor(el) { this._el = el; } set value(newVal) { this._el.innerHTML = `The value is ${newVal}`; } } const output = document.getElementById('output'); const x = new ValOutput(output); x.value = 100; setTimeout(() => { x.value="after timeout"; }, 2000); 
 <div id="output"></div> 

以下是吸氣劑的兩個原因:

1.計算該值

 class Rect { constructor(l = 0,t = 0,r = 0,b = 0) { this.left = l; this.top = t; this.right = r; this.bottom = b; } get height() { return this.bottom - this.top; } get width() { return this.right - this.left; } } let a = new Rect(0, 10, 33, 55); console.log(a.width, a.height); a = new Rect(35, 50, 200, 200); console.log(a.width, a.height); 

2.您正在代理另一個對象的值

 class OtherThing { constructor(a) { this.a = a; } } class MyObj { constructor(oVal = 0) { this._otherThing = new OtherThing(oVal); } get a() { return this._otherThing.a; } } const x = new MyObj(); console.log(xa); const y = new MyObj('tacos'); console.log(ya); 

隱藏私有變量

getterssetter是隱藏私人數據的好方法。 是的,我知道ES規范引入了私有變量,但這里有一個例子,直到該規范是標准的。

 const privateVars = new WeakMap(); class MyObj { constructor(inVal) { const pVars = { age: inVal, dog: '' } privateVars.set(this, pVars); } get dog() { return privateVars.get(this).dog; } set dog(newVal) { privateVars.get(this).dog = newVal; } } const x = new MyObj(10); const y = new MyObj(20); x.dog = "woof"; y.dog = "bark"; console.log(x.dog); console.log(y.dog); 

你需要gettersetters嗎? 不,他們有必要嗎? 是。

Getter和setter用於訪問PRIVATE PROPERTY或從外部修改它。 GETTER是一個用於讀取屬性的函數。如果你想從外部設置私有屬性的值,我們定義一個SETTER函數。 這是一個例子:

function Circle(radius){
this.radius=radius;
let originPoint={x:0,y:0};  //originPoint is a private property.
this.area=function(){console.log("area")};

Object.defineProperty(this,originPoint,{
    get:function(){
return originPoint;
};
set:function(value){
originPoint=value;}
}
}
const circle=new Circle(10);
circle.originPoint  //will call "get" function
circle.originPoint={x:2,y:3}

實現getter和setter功能的一個主要原因是關閉一個功能差距,需要人們破解js解釋器/瀏覽器以實現瀏覽器可以執行的一項功能:

element.innerHTML = "<div> some HTML string </dif>";

現在, innerHTML可能看起來像一個屬性,但它實際上更像是一個函數。 它實際上是一個HTML編譯器。

你可以通過嘗試做到這一點:

element.innerHTML += "<table>";
element.innerHTML += "<tr><td>test</td></tr>"; // does not work

這是因為對innerHTML的第一次“調用”將html編譯為:

<table></table>

第二行將失敗,因為表外的<tr>是無效的HTML。

使用getter和setter,你最終可以在純javascript中實現這樣的功能 - 使屬性訪問觸發函數調用。

當然, innerHTML只是getter和setter的一個例子,也是API的一個非常糟糕的例子。 這取決於你的創造力,你可以用吸氣劑和制定者實際做什么。

現在,根據我個人的意見(這只是我的觀點,所以把它當作它的價值):我認為innerHTML提供了一個很好的例子,說明為什么通常不應該使用getter和setter。 <table>的困惑是打破用戶期望的一個很好的例子。 如果innerHTML被實現為element.appendHTML()那么它的行為就不那么令人驚訝了。 作為程序員,如果屬性訪問做了我不期望的事情,我會感到非常驚訝。

也就是說,我高興存在getter和setter,使語言庫功能可以自行實現,而無需訴諸於C / C ++中的黑客攻擊。

使用gettersetter方法取決於你在類中的屬性,如果你想使一個屬性只是只讀它的真實使用getter方法如下:

 function Person(name, age){ var _name = name; this.age = age; this.getName = function(){ return _name; } } var teacher = new Person('Sara', 24); //now you can just get the name of teacher alert(teacher.getName()); 

我們使用該類的原因是保存單個實體的所有屬性。但是您可以通過創建對象來完成,並且可以在需要時將屬性附加到該對象。

當代碼變大時,您無法調試代碼失敗的位置。如果您遵循結構,您可以輕松地dubug.Because因為每個實體將在單獨的文件中,邏輯將是分開的。

但是JavaScript是一種面向對象的編程語言。我們之所以使用類而不是對象,這對於getter和setter來說是一樣的。它不像你可以在哪里使用你不需要的地方。這是一個很好的做法來設置和獲取所有屬性通過setter和getters。

在某個時間點之后,您可能會在設置屬性時添加一些條件,例如,如果一個人的年齡大於100,則不應該在該屬性中設置。在那個時間點,您需要更改基類,以及你的孩子班。這將是我們生活中最艱難的部分(代碼重構)。為了避免這些問題並使你的變量安全,從我的觀點來看,我們應該使用getter和setters.sorry來獲得長期答案

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM