【问题标题】:Is there a more elegant approach for private members of class instances?对于类实例的私有成员是否有更优雅的方法?
【发布时间】:2016-03-25 06:04:23
【问题描述】:

我想为类以及类实例创建设置一个设计标准。结合来自多个网站的大量英特尔(例如来自 stackoverflow),终于有一种方法可以相对最大的灵活性。我的目标正是让代码结构的行为类似于更多定义的 Java 类等。

这是我目前所拥有的工作代码n-p(包括解释):

var MyClass = function (prop1)
{
    var _class = MyClass;
    var _proto = _class.prototype;

    // public member of constructed class-instance
    this.prop1 = prop1;

    // private static property as well as private member of class-instances
    // (see getter below!)
    var prop2 = this.prop1 * 10;
    // need to use this. instead of _proto because the property prop2 of
    // the class itself would be returned otherwise
    this.getProp2 = function ()
    {
        return prop2;
    }

    // 1 function for all instances of the class
    // reached by a fallback to the prototype
    _proto.protoAlert = function ()
    {
        // must call this.getProp2() instead of using prop2 directly
        // because it would use the private static member of the class
        // itself instead the one of the class-instance
        alert(this.prop1 + " " + this.getProp2());
    }
};

var c1 = new MyClass(1);
c1.protoAlert();
var c2 = new MyClass(2);
c2.protoAlert();
c1.protoAlert();

到目前为止效果很好。但是,要避免引发脚本错误和未发现的不当行为,需要采取一些障碍。私有属性prop2 存在于类和类实例中。这可能是一个无意的双重身份。此外,类实例的私有属性只能通过 setter 和 getter 函数正确访问。这并不是最糟糕的事情,因为它强制使用一种通用的方式来访问私有变量。缺点是:必须使用 this. 调用 Setter 和 getter 才能实际引用类实例的 prop2 然后返回它。至于类继承——我还没有按照我目前的标准来研究这个话题。希望它也能成功。

有没有更优雅的解决方案,或者至少有一个不太容易出错的解决方案?

提前谢谢你!

【问题讨论】:

  • 您应该立即做的第一件事是stop assigning prototype methods inside the constructor
  • 个人意见:更优雅的解决方案是根本不使用类。在 javascript 中,组合优于继承。另外,如果你想要优雅,请参阅 bergis 评论,不要在类中声明原型,这是自找麻烦。
  • 你为什么不使用已建立的MyClass.prototype.protoAlert = function .. 方法(在构造函数之外!),而是在严重地重新发明轮子......?!
  • here you go,完成了模块化、封装和继承。或者现在只使用 ES6 class 语法。
  • “私有属性prop2 存在于类和类实例中” – 什么?不清楚这意味着什么或你是如何得出这个结论的。

标签: javascript class instance private


【解决方案1】:

JavaScript 并没有真正为私有属性提供实用的模式。只要您在构造函数中定义了所有方法,您使用的模式就可以工作。您应该记住,这意味着每次创建类时,您都会创建所有方法。

如果你想一想,私有变量在程序中不服务任何功能它们服务于程序员要记住,他应该和他应该做什么不会改变。因此,您可以简单地使用一些命名模式。我在其他人的代码中看到了很多:

function MyClass() {
    // Private property
    this._helloWord = "Hello word.";
}
// From outside, accessed as `helloWord`, without underscore
Object.defineProperty(MyClass.prototype, "helloWord", {
    get: function() {console.log("helloWord getter");return this._helloWord;},
    set: function(value) {console.log("helloWord setter");return this._helloWord = value;},
};
MyClass.prototype.alertProp = function() {
    alert(this._helloWord);
}
// Accessing from the outside:
var instance = new MyClass();
alert(instance.helloWord); // will activate the getter function

大多数人会立即明白_underscored 变量有什么特别之处。您也可以通过这种方式使变量保持不变:

Object.defineProperty(MyClass.prototype, "helloWord", {
    value: "Hello world",
    writable: false // <----
};

详细了解Object.defineProperty。您还应该了解 Javascript 的结构与 OOP 语言的结构有些不同。如果你尝试在上面推送其他语言的模式,会导致性能和结构问题。

【讨论】:

  • 您不能在属性描述符中同时使用getwritable
  • 我希望能成功解决Object.defineProperty 问题,因为它使代码相当混乱。然而,除了本地包含类概念的较新标准之外,这似乎是拥有私有和公共参数的最干净的方式。对于继承,我将不得不使用问题评论部分中建议的组合。
  • @FlorianR.Klein 我倾向于为Object.defineProperty 编写本地包装器 - 稍微自动化流程的函数,尤其是在存在重复模式时。
  • @TomášZato 这将影响最小化了一点。感谢您的提示。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-08
  • 2016-08-03
  • 2012-07-23
  • 1970-01-01
  • 1970-01-01
  • 2012-12-16
相关资源
最近更新 更多