1.背景
在ES6中,我们对类的定义如下
1 class Person { 2 // 构造函数 3 constructor (name) { 4 // 属性初始化 5 this.name = name; 6 } 7 8 // 成员方法 9 sayName () { 10 console.log(this.name); 11 } 12 13 // 静态方法 14 static sayHi () { 15 console.log("Hi~"); 16 } 17 }
其实本质还是基于javascript原型链机制开发的语法糖
2. 深入setter/getter
2.1 setter/getter的调用执行时机
1 class Person { 2 constructor(name,age) { 3 this.name = name; 4 this.age = age; 5 } 6 7 set name(name) { 8 console.log("setter"); 9 this.name = name; 10 } 11 12 get name() { 13 console.log("getter"); 14 return this.name; 15 } 16 }
发现上面的代码报错
/**
* 这是因为,在构造函数中执行this.name=name的时候,就会去调用set name,
* 在set name方法中,我们又执行this.name = name,进行无限递归,
* 最后导致栈溢出(RangeError)。
* */
我们稍作修改,让这个代码可以正常执行,达到我们想要的效果。
1 // 针对上面的情况,稍作修改 2 class Person { 3 constructor(name,age) { 4 this.name = name;// 执行这里 --- 1 5 this.age = age; 6 } 7 8 set name(name) { // 进入到这里进行设置 -- 2 9 console.log("setter"); 10 this._name = name; 11 } 12 13 get name() { // 在这里将对应的值返回 --- 3 14 console.log("getter"); 15 return this._name; 16 } 17 18 sayName() { // 这里的调用,又从 1-2-3 19 console.log(this.name); 20 } 21 } 22 let p2 = new Person("lisi",22); 23 console.log(p2);// 真实的属性是 age _name 而不是name 24 p2.sayName(); 25 console.log(p2._name);// 如果你访问的是 p2.name 最后会执行 1-3 这两个步骤,会打印出getter
控制台结果如下:
/**
* 总结
* 只要this.+属性名 和get 属性名/ set 属性名 中,属性名一致,
* this.name 会去调用getter 和 setter ,也就是说 getter和setter是hock函数
* 而真实存储的属性是 _name 我们可以在实例化后,直接获取
* */
2.2 只有getter定义只读属性
1 // 只有getter定义只读属性 2 class foo { 3 constructor(name) { 4 this.name = name; 5 } 6 7 get name() { 8 console.log(`getter函数`); 9 return this.name; 10 } 11 } 12 //Cannot set property name of #<foo> which has only a getter 13 let p3 = new foo("李四");
/**
* 总结:
* 当一个属性只有getter没有setter的时候,我们是无法进行赋值操作的(第一次初始化也不行),这一点需要注意
* 当没有getter和setter时,就可以正常读写属性
* */