Array作为JavaScript中的受保护Object属性

时间:2014-06-19 13:33:33

标签: javascript arrays protected

我正在尝试构建一个JavaScript构造函数,该构造函数将数组作为具有只读访问权限的属性:

var Word = function() {
  var _occurrences = [];
  Object.defineProperties(this, {
    "occurrences": {
      get: function() {
        return _occurrences;
      }
    },
    "addOccurence": {
      value: function(occ) {
        _occurrences.push(occ);
      }
    }
  });
};

数组本身是一个私有变量,有一个指向它的get-er。

var myWord = new Word();
myWord.addOccurrence(123);
var occ = myWord.occurrences;

一切正常。

myWord.occurrences = [];

被阻止,应该是。但令人惊讶的是,这有效:

myWord.occurrences.push(321);

保护属性使其不受新分配的影响,但不能通过Array方法保持写入权限 - 即使它只通过getter访问。这使Object.defineProperty()对我来说毫无意义。

Object.freeze() / Object.seal()不是一个选项,因为我需要addOccurrences()方法的写入权限。

有什么想法吗?我忽略了什么吗?

2 个答案:

答案 0 :(得分:4)

JavaScript仅为您提供对象(包括数组)的引用。当您return _occurrences时,您将返回对数组的引用,以便您可以对其进行操作。

如果要防止这种情况,请改为返回数组的副本。

return _occurrences.concat();

答案 1 :(得分:1)

如果你想让对象私有,你应该这样写:

(function(window) {
  var _occurrences = [];

  function Word() { /*empty constructor*/ }

  Word.prototype.get = function() {
    return _occurrences;
  };
  Word.prototype.add = function(value) {
    _occurrences.push(value);
  };

  window.Word = Word
})(window);

这样,范围仅在创建的对象实例中可用。无法覆盖实例中_occurences的值。

创建了此解决方案的示例:http://jsfiddle.net/fxxaB/2/

但是如果你想在阵列外部访问数组,我会建议以下解决方案添加一个函数,如下例所示:

Word.prototype.instance = function() {
  return _occurences.copy();
}

这样可以访问数组,但仍然无法操作值。