为什么我的javascript getter / setter需要下划线?

时间:2017-11-06 21:27:32

标签: javascript

a上执行[[Get]]或[[Put]]操作会抛出一个RangeError,指出Maximum call stack size exceeded指向getter中的this.a=在setter中。

let someObject = {
  get a() {
    return this.a;
  },
  set a(val) {
    this.a = val;
  }
}

someObject.a;  // Error
someObject.a = 5;  // Error

如果强调了getter和setter中的属性,则它们可以正常工作:

let someObject = {
  get a() {
    return this._a_;
  },
  set a(val) {
    this._a_ = val;
  }
}

我已经在Chrome中的节点环境和v10引擎中对此进行了测试,同样的事情发生了。

这种混乱。发送帮助。

3 个答案:

答案 0 :(得分:2)

您需要拥有一个与getter / setter不同的变量。最常见的方法是使用_为变量添加前缀。

否则,如果你不这样做,你将无休止地调用getter / setter。

class A {
    constructor() {
        this._a = '';
    }

    get a() {
        // If we don't call it like this
        // We will be calling the getter again
        // Which in return will call itself again
        return this._a
    }
}

答案 1 :(得分:1)

一旦使用某个属性的setter定义了一个对象,该setter 总是用于设置属性值 - 即使在setter本身内也是如此!如果您尝试在setter中使用简单赋值设置属性,JavaScript将再次调用setter,您将获得无限递归。

使用像“_”这样的前导特殊字符作为第二个“秘密名称”是一种常见的惯例。但是,该属性仍然是外部可见的(尽管它可以是不可枚举的)。在较新的JavaScript环境中可用的另一种方法是使用Symbol实例而不是属性名称。符号实例保证您的内部属性标识符不会与应用程序中某些其他源的另一个属性名称冲突。

所以:

let someObject = function() {
  var aKey = Symbol();
  return {
    get a() {
      return this[aKey];
    },
    set a(value) {
      this[aKey] = value;
    }
  };
}();

该代码使用闭包为实际属性键创建私有变量,外部看起来像一个名为“a”的属性。任何其他代码都不可能意外地“踩”setter / getter对使用的私有实际属性,因为这就是Symbol的用途。

答案 2 :(得分:1)

因为通过执行return this.a您正在访问a属性,该属性会触发getter函数,该函数访问a属性,从而触发getter函数,该函数访问a属性,触发getter函数......无限循环。

同样的setter。