1. 背景
在es6中,我们可以用class
关键字来定义类,语法如下
class Person {
// 构造函数
constructor (name) {
// 属性初始化
this.name = name;
}
// 成员方法
sayName () {
console.log(this.name);
}
// 静态方法
static sayHi () {
console.log("Hi~");
}
}
其实本质还是基于javascript原型链机制开发的语法糖
,其中,本人对setter/getter进行一番研究,发现了不少坑。
2. 深入setter/getter
2.1 setter/getter的调用执行时机
class Person {
constructor (name, age) {
this.name = name;
this.age = age;
}
set name (name) {
console.log("setter");
this.name = name;
}
get name () {
console.log("getter");
return this.name;
}
}
var p = new Person("zhang", 25);
很快,我们就会发现代码报错了
这是因为,在构造函数中执行this.name=name
的时候,就会去调用set name
,在set name方法中,我们又执行this.name = name
,进行无限递归,最后导致栈溢出(RangeError)。
我们稍作修改,让这个代码可以正常执行,达到我们想要的效果。
class Person {
constructor (name, age) {
this.name = name;
this.age = age;
}
set name (name) {
console.log("setter");
this._name = name;
}
get name () {
console.log("getter");
return this._name;
}
// 加一个成员方法
sayName () {
console.log(this.name);
}
}
var p = new Person("zhang", 25);
p.sayName();
执行结果为
到这里就可以明白了,原来只要this.name中的属性名和set name/get name后面的name一致,对this.name就会调用setter/getter,也就是说setter/getter是hook函数
,而真实的存储变量是_name
,我们可以在代码中直接获取它。
class Person {
constructor (name, age) {
this.name = name;
this.age = age;
}
set name (name) {
console.log("setter");
this._name = name;
}
get name () {
console.log("getter");
return this._name;
}
// 加一个成员方法
sayName () {
console.log(this.name);
}
}
var p = new Person("zhang", 25);
console.log(p._name); // "zhang"
执行结果为
注意到结果并没有执行getter,因为我们直接访问了p._name
,而不是p.name
2.2 只有getter定义只读属性
当一个属性只有getter没有setter的时候,我们是无法进行赋值操作的(第一次初始化也不行),这一点也是相当地坑
。例如
class Person {
constructor (name) {
this.name = name;
}
// 只有getter
get name () {
console.log("getter");
return this.name;
}
}
var p = new Person("zhang");
执行结果为
当没有getter和setter时,就可以正常读写属性
原文:https://segmentfault.com/a/1190000007356931