JavaScript中的getter和setter
在 C++, C#, Java 等面向对象语言中,对象由两部分组成:属性和方法。通常属性是私有成员或保护成员,不能从对象外部直接访问;方法是公有成员,供外界间接访问对象的内部属性,以此来实现数据隔离。利用伪代码来简单演示如下:
构造一个只有一个私有成员而没有任何共有方法的对象 obj
var obj = {
private int attr1 = 1024,
}
不能直接访问和修改attr1
print(obj.attr1) // Error: can't access attr1 of obj
obj.attr1 = 4201 // Error: can't access attr1 of obj
而 Javascript 中则没有这样的数据隔离机制(不过 ES6 中可以通过Symbol来实现相似的定义私有成员的方法) , 你可以定义一个对象,然后随意修改它的属性:
var obj = {
attr1: 1024
};
console.log(obj.attr1); // 1024
obj.attr1 = 1000;
console.log(obj.attr1); // 1000
虽然 Javascript 没有提供硬性的对象成员隔离机制,但通过定义方法来间接访问数据成员的场景还是存在的,这就是 getter 和 setter 存在的意义。你可能以为我接下来会讲讲 JavaScript 的 setter 和 getter 是怎么运作的, You're wrong. 自己去 MDN 看吧!这里有必要讲的是 Vuex 的 getter 和 setter 是怎么工作的,因为身边很多朋友都踩过坑。看下边的例子:
// 先在Vuex store里定义一个cat
const zoo = {
state: {
cat: {
name: 'tom'
}
},
mutations: {
changeCatColor(color) {
state.cat.color = color
}
}
}
// 然后在系统中某个地方修改下上面的cat的color
store.commit('changeCatColor', 'red')
// 在某个叫foo-bar的component中获取store中的cat的color,将其渲染在视图上
{
computed: {
catColor() {
return this.$store.state.cat.color
}
}
}
// 猜猜结果是什么?
// 正确答案:
// zoo.state变成了
{
cat: {
name: 'tom',
color: 'red'
}
}
// foo-bar中
console.log(this.catColor) // undefined
为什么会这样?因为 Vuex 之所以能将 state 中数据的变化传递到组件中,是因为 Vuex 在初始化 state 时会通过字段的 setter 来设置监听器, 当字段值改变时,就可以把新值传递给 getter。示例中的 cat.color 没有在 state 初始化时声明,所以没有监听器,就导致虽然 state.cat.color 改变了, 但没有传递到组件中。所以,最重要的一句话:在使用 Vuex 的 state 之前,一定要初始化所有属性!