数组在JavaScript中作为受保护的对象属性

Array as protected Object property in JavaScript

本文关键字:受保护 对象 属性 JavaScript 数组      更新时间:2023-09-26

我试图建立一个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()方法进行写访问。

任何想法?我是不是忽略了什么?

JavaScript只提供对对象(包括数组)的引用。当执行return _occurrences时,返回对该数组的引用,以便对其进行操作。

如果你想避免这种情况,返回数组的副本。

return _occurrences.concat();

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

(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);

这样,作用域仅在对象的创建实例中可用。实例中的_occurs值不能被覆盖。

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

但是如果你想在数组外访问数组,我建议以下解决方案添加一个函数,如下面的例子:

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

这样数组是可访问的,但值仍然不能被操作。