简体   繁体   English

使用getter&setter和公共属性之间的区别

[英]Difference between using getter&setter and public properties

I am new to JS and was learning abstraction and the use of getter and setters in JS. 我是JS的新手,正在学习JS中的抽象以及getter和setter的使用。 So, as far as I know, getter and setter can be achieved with object.defineProperty but look guys, what is the reason for giving access to private property via getter and setter instead of public property. 因此,据我所知,可以使用object.defineProperty来实现getter和setter,但是伙计们,是什么原因允许通过getter和setter而不是公共财产访问私有财产。 Since, with getter we can read private property and with setter we can set new value to private property. 因为,使用getter可以读取私有财产,而使用setter可以将新值设置为私有财产。 Isn't it the same if we use public property which also allows to read value of that public property and set new value to it. 如果我们使用公共财产也可以读取公共财产的价值并为其设置新的价值,这是不一样的。 I just cannot get why to use getter and setter when we can use public property to achieve both getter and setter. 当我们可以使用公共属性同时实现getter和setter时,我只是无法理解为什么要使用getter和setter。 Hope you got my point. 希望你明白我的意思。

A getter/setter is generally useful for when, on property access, the class wants to do something in addition to simply setting/retrieving the data. 通常,在属性访问时,除了简单地设置/检索数据之外,类还需要执行某些操作时,getter / setter很有用。 For example: 例如:

 class MyClass { constructor() { this.setHistory = []; } set item(newVal) { this.setHistory.push(newVal); this._item = newVal; } get item() { return this._item; } } const f = new MyClass(); f.item = 'foo'; f.item = 'bar'; console.log(f.setHistory); 

Above, storing the "history" of what items have previously been set is possible with a setter function. 在上面,可以使用设置功能存储以前设置了哪些项目的“历史记录”。 Without the setter function, with only a public item property, the class cannot save the history. 如果没有setter函数,则只有一个公共item属性,该类将无法保存历史记录。

If all a getter/setter is doing is setting or retrieving a value, you're right that it's mostly useless, eg: 如果getter / setter所要做的只是设置或检索值,那么您说对了,它几乎没有用,例如:

 class MyClass { set item(newVal) { this._item = newVal; } get item() { return this._item; } } const f = new MyClass(); f.item = 'foo'; f.item = 'bar'; console.log(f.item); 

Here, the setters and getters aren't doing anything useful at all, so you may well just remove them. 在这里,setter和getter根本没有做任何有用的事情,因此您可以删除它们。 Generally, use a setter/getter when you want to do something other than just store/retrieve values. 通常,当您要执行除存储/检索值之外的其他操作时,请使用setter / getter。

Setters and getters can also be useful to hide implementation details unimportant to consumers. setter和getter还可用于隐藏对消费者不重要的实现细节。 (For example, assigning to .innerHTML is pretty similar to invoking a setter.) (例如,分配给.innerHTML 调用设置器非常相似 。)

They can also be useful when debugging, to (for example) log when an object is being changed. 它们在调试时也很有用,例如在更改对象时记录日志。

One caveat: the first snippet above doesn't actually use "private" properties, it simply uses the _ -prefix convention to indicate that the property shouldn't be used externally. 一个警告:上面的第一个代码片段实际上并不使用“私有”属性,它只是使用_ -prefix约定来指示该属性不应在外部使用。 For a true private property that can't be accessed from the outside, you should define a WeakMap and create the class with an IIFE: 对于无法从外部访问的真实私有属性,应定义WeakMap并使用IIFE创建类:

 // with this class, // neither item nor history can be accessed without going through the getters const MyClass = (() => { const privateDatas = new WeakMap(); return class MyClass { constructor() { privateDatas.set(this, { setHistories: [] }); } set item(newVal) { const privates = privateDatas.get(this); privates.setHistories.push(newVal); privates.item = newVal; } get item() { return privateDatas.get(this).item; } getSetHistory() { return privateDatas.get(this).setHistories; // if you want to make sure the internal array doesn't get mutated outside, // return a copy: .setHistories.slice() } } })(); const f = new MyClass(); f.item = 'foo'; f.item = 'bar'; console.log(f.getSetHistory()); 

The field don't really needs to exist for each getter/setter. 每个getter / setter都不需要真正存在该字段。 One example is the Date which I believe only store milliseconds but you can get all the information (it doesn't use the new getter/setter syntax but the concept is the same) 一个示例是Date ,我相信它只存储毫秒,但是您可以获得所有信息(它不使用新的getter / setter语法,但是概念相同)


Here is a simple wrapper to Date using the new syntax, hope it makes it more clear. 这是使用新语法的Date的简单包装,希望可以使它更加清晰。

 class NewSyntaxDate{ constructor(){ this.date = new Date() } get Hours(){return this.date.getHours()} set Hours(h){this.date.setHours(h)} get Minutes(){return this.date.getMinutes()} set Minutes(m){this.date.setMinutes(m)} } let date = new NewSyntaxDate() console.log(date.Hour) console.log(date.Minutes) console.log(date.date) date.Hours = 0 date.Minutes = 0 console.log(date.date) 


Other use include getter-only or setter-only. 其他用途包括仅使用getter或仅使用setter。 Data validation (before set to internal field). 数据验证(设置为内部字段之前)。 Alias for other field... 其他领域的别名...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM