在复习对象访问器的时候,我就犯了一个简单的错误,也让我意识到我是对getter和setter是理解不到位的。先看看我的代码和错误提示:


错误提示是:person.messageAre不是函数。我感到很困惑,因为我在person里对messageAre的写法看起来就像是一个函数。我立马再去认真学一下getter和setter,发现以下才是使用 setter 设置对象属性和getter获取属性的正确用法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | var person = { name: "QQ", age: 18, get messagesAre(){ console.log('get messagesAre'); return `${this.name} ${this.age}`; }, set messagesAre(m){ console.log('set messagesAre'); [this.name,this.age] = m.split(' '); } } document.getElementById('getSth').innerText = person.messagesAre; person.messagesAre = 'QQiukulele 16' document.getElementById('getSth').innerText = person.messagesAre; |

认识getter和setter
访问器属性由“getter”和“setter”方法表示。在一个对象字面量中,它们由get和set表示,后面是与它相关得属性(messageAre)和一个函数体。函数体内定义了当属性被访问或修改时得行为。所以person.messageAre,它不是方法。
这下算是弄明白我的疑惑了,那为什么要使用getter和setter呢?
- 它提供了更简洁的语法
- 它允许属性和方法的语法相同
- 它可以确保更好的数据质量
- 有利于后台工作
从外部看,访问器属性是与常规属性类似的。这也是访问器属性的思想。
在我看来,在读取或操作对象的属性时,getter和setter的用法会比调用函数看起来更让人明了和接受。赋值就赋值,读取值就“.”来获取。??
getter /setter还可以当作**“实际”属性值的包装器**,以获得对对象属性操作的更多控制。下面是一个例子,利用setter hobby在对person.hobby赋值时判断是否"唱"出一句"You don’t know about me",hobby会存储在_hobby属性中,通过getter 和 setter访问。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | var person = { get hobby(){ //记得保持和你要操作的属性名一致 return this._hobby; }, set hobby(h){ if(h !== '弹琴'){ console.log("You don't know about me"); return ; } this._hobby = h; } } person.hobby = '弹琴'; console.log(person.hobby); //弹琴 person.hobby = '跑步'; //You don't know about me console.log(person._hobby) //弹琴 但是不推荐这样访问,因为_开头的属性默认是内部属性,不要外部访问 |
Object.defineProperty() 方法也可用于添加 getter 和 setter:
Object.defineProperty() 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | var person = {}; var name = ''; Object.defineProperty(person,'name',{ set : function(value){ name = value; }, get : function(){ return '我的名字是'+name; } }); person.name = 'QQ'; console.log(person.name); //我的名字是QQ console.log(person); |

以上,通过Object.defineProperty() 方法定义的访问属性器hobby包含一个getter函数和一个setter函数。假如我们把Object.defineProperty() 方法定义部分给注释掉,继续打印person对象,会发现如下结果,属性name自己本身也带有get 和 set方法的。

实际上,每个属性都有原生的setter和getter,但是他们不会被显示地显示出来。不论是对象字面量还是用Object.defineProperty() 方法,都是对对象原生的setter和getter的重写。
初步理解vue的双向数据绑定原理
学习setter和getter的过程,多少会看到一点vue双向数据绑定的身影。理解以及会正确运用getter和setter对于后面vue的双向数据绑定MVVM的学习理解很有帮助~Vue会对
1 2 3 4 5 6 7 8 9 10 11 | var vm = new Vue({ el:'#app', data: { obj:{ message : 'QQiukulele' } }, created: function(){ console.log(this.obj) } }); |

对比上面用Object.defineProperty()为一个对象显示地声明getter和setter的打印结果,看起来是和上面打印的vue数据很类似。
vue内部是怎样实现双向数据绑定的?下面是摘自别人的总结介绍o( ̄▽ ̄)ブ:
数据劫持: vue.js 则是采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应的监听回调。
这仅仅是对vue的双向数据绑定原理的初步理解,深入理解需更多学习以上也是我的学习和理解,若有描述不正确,欢迎指出!若有更深入的理解,欢迎交流~
? 参考文章链接:
?? https://www.jackfranklin.co.uk/blog/es5-getters-setters/
?? https://github.com/DMQ/mvvm