0

我希望使用带有私有可继承属性的https://github.com/mozilla/BrowserQuest/blob/master/server/js/lib/class.js以及其中的一些 getter 和 setter。

基本上,我希望 getter / setter 修改私有属性和子类以继承 setter、getter 和私有属性。这是我到目前为止得到的:

var Person = Class.extend({
    init: function( name )
    {
        var name = "~";

        this.myName = name;

        return {
            set myName( value )
            {
                name = value + " +?";
            },
            get myName()
            {
                return name + "^^^^^^^^^";
            }
        }
    }
});
var c  = new Person( "cheese" );
console.log(c.myName);
c.myName = "zoom";
console.log(c.myName);

跟踪:未定义缩放

奇怪的是,我的编辑器(Webstorm)将 c.myName 视为 setter/getter,但编译器认为它是未定义的公共属性 :(

任何帮助,将不胜感激。这是 Nodejs,但我认为问题在于 javascript。

4

1 回答 1

4

我假设 Node.js 或任何其他可以使用整个 EcmaScript 5 的环境。

如今,在 JavaScript 中拥有真正私有数据的唯一方法是在构造函数中保留一个变量,这就是您正在做的事情。但是,您returninit函数中的使用感到困惑。虽然该init函数几乎是构造函数,但它并没有被完全调用,所以return什么也不做。即使它做了什么,你想要的是将一个属性添加到this,而不是返回一个新对象。所以基本上你必须将其更改returnObject.defineProperty

init: function (name) {
  // notice that the private variable has a different name
  // than the parameter
  var privateName = '~';

  Object.defineProperty(this, 'myName', {
    set: function (value) {
      privateName = value + " +?";
    },
    get: function () {
      return privateName + "^^^^^^^^^";
    }
  });

  this.myName = name;
}

这仍然有继承的限制。如果您想从 Person 类继承并修改 getter 和 setter,您必须获取属性描述符,修改它并重新定义属性。那很痛苦。而且它不支持访问“超级getter/setter”。为了避免我们通常在 JavaScript 中所做的是忘记拥有真正的私有属性并按照约定使用私有属性,私有属性的名称以_. 然后你可以像这样在原型中简单地定义你的getter和setter:

var Person = Class.extend({
  init: function(name) {
    // the private name property
    this._name = '~';

    this.myName = name;
  },
  set myName(value) {
    this._name = value + " +?";
  },
  get myName() {
    return this._name + "^^^^^^^^^";
  }
});

这将让您在使用继承时访问超级 getter/setter。

有一个尖端功能可以让您拥有真正的私有并继承 getter 和 setter:WeakMap。WeakMap 基本上是一个对象,它在其他两个不计入垃圾收集的对象之间创建关系。最后一部分对于内存管理很重要,而第一部分是让你拥有真正私有的部分。您可以在 Firefox 的 Beta 版本和带有--harmony_collections标志的 Node.js 中尝试 WeakMaps。以下是它的工作原理:

function privatize() {
  var map = new WeakMap();
  return function (obj) {
    var data = map.get(obj);
    if (!data) {
      map.set(obj, data = {});
    }
    return data;
  };
}

var Person = (function () {
  var _private = privatize();

  return Class.extend({
    init: function(name) {
      // the private name property
      _private(this).name = '~';

      this.myName = name;
    },
    set myName(value) {
      _private(this).name = value + " +?";
    },
    get myName() {
      return _private(this).name + "^^^^^^^^^";
    }
  });
}());
于 2013-04-06T15:49:33.850 回答