简体   繁体   English

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

[英]Why does my javascript getter/setter require underscores?

Performing a [[Get]] or [[Put]] operation on a throws a RangeError that states Maximum call stack size exceeded pointing to the this.a in the getter and the = in the setter. 执行[获取]]或[将]操作上a抛出,指出一个引发RangeError Maximum call stack size exceeded指向this.a在吸气和=的制定者。

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

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

If the properties inside the getter and setter are underscored they work however: 如果强调了getter和setter内部的属性,它们将起作用:

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

I've tested this in both the node environment and the v10 engine in Chrome and the same thing happens. 我已经在Chrome的节点环境和v10引擎中对此进行了测试,并且发生了相同的事情。

Such confusion. 如此混乱。 Send help. 发送帮助。

You need to have a variable that has a different name then the getter/setter. 您需要拥有一个与getter / setter命名不同的变量。 The most common way is to prefix the variable with an _ . 最常见的方法是在变量前加上_

Otherwise if you don't do this you will have an endless loop of calls to the 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
    }
}

Because by doing return this.a you're accesing the a property, which triggers the getter function, which accesses the a property, which triggers the getter function, which accesses the a property, which triggers the getter function... Endless loop. 因为这样做return this.a你accesing的a属性,它触发getter函数,它访问a属性,它触发getter函数,它访问a属性,它触发getter函数...无限循环。

Same for setter. 对于二传手也一样。

Once an object has been defined with a setter for some property, that setter is always used to set the property value — even inside the setter itself! 用某个属性的设置器定义一个对象后,该设置器将始终用于设置属性值,即使在设置器内部也是如此! If you attempt to set the property with simple assignment inside the setter, JavaScript will call the setter again, and you get infinite recursion. 如果您尝试通过设置器内部的简单分配来设置属性,JavaScript将再次调用设置器,您将获得无限递归。

Using a leading special character like "_" for a second "secret name" is a common convention. 通常将第二个“秘密名称”使用前导特殊字符(如“ _”)。 However, that property is still externally visible (though it can be made non-enumerable). 但是,该属性在外部仍然可见(尽管可以将其设为不可枚举)。 Another approach available in newer JavaScript environments is to use a Symbol instance instead of a property name. 较新的JavaScript环境中可用的另一种方法是使用Symbol实例而不是属性名称。 Symbol instances guarantee that your internal property identifier cannot ever collide with another property name from some other source in the application. 符号实例可确保您的内部属性标识符永远不会与应用程序中其他来源的另一个属性名称发生冲突。

So: 所以:

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

That code uses a closure to create a private variable for the actual property key for what externally looks like a property called "a". 该代码使用闭包为实际的属性键(在外部看起来像称为“ a”的属性)创建私有变量。 It won't be possible for any other code to accidentally "step on" the private actual property used by the setter/getter pair because that's what Symbol is for. 其他任何代码都不可能意外地“踩踏”设置器/获取器对使用的私有实际属性,因为这就是Symbol的目的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM