学习es6 setter/getter研究

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时,就可以正常读写属性
* */

 

posted @ 2018-03-03 21:54  星辰之夜  阅读(3059)  评论(0编辑  收藏  举报