Javascript Accessor属性混乱

时间:2016-06-22 14:58:31

标签: javascript properties accessor

我不确定为什么这段代码会给我一个错误。我想要做的就是创建一个具有数组作为属性的对象。我想用setter和getter实现这个目的但由于某种原因,当我在setArray函数中执行this.array = []时,我得到超出最大调用堆栈大小。我究竟做错了什么 ?我对Javascript的访问者属性缺少什么。

var obj = {
  set array(size) {
   this.array = [];
   for (var i = 0; i < size; i++){
        this.array[i] = i; 
   }
  }
};


var myObj = Object.create(obj); 
myObj.array = 20; 

3 个答案:

答案 0 :(得分:4)

你从setter中分配了一个带有setter的属性,这就是为什么它会永远递归:

var obj = {
    set array(size) {                   // <== The property is called `array`
        this.array = [];                // <== This calls the setter
        for (var i = 0; i < size; i++){
            this.array[i] = i;          // <== This would fail because there's no getter
        }
    }
};

您必须将值存储在其他位置,例如,我们在这里创建一个私有范围并关闭变量:

var obj = (function() {
    var array = [];
    return {
        set array(size) {
            array = [];                // No `this` here
            for (var i = 0; i < size; i++) {
                array[i] = i;          // No `this` here
            }
        },
        showArray() {
            console.log(array);
        }
    };
})();
  
var myObj = Object.create(obj); 
myObj.array = 20; 
myObj.showArray();

你问过要避免这个功能。您需要该函数才能使属性的值真正私有。但如果你不想出于某种原因使用它,并且你并不担心它是真正私密的,你可以做ZoltánTamási在his answer中所做的事:在同一个对象上使用另一个属性。他的回答在底层属性上使用_前缀(例如,_array),这是JavaScript中的一个非常常见约定,“单独留下它,它是'私有'”即使没有私人财产。事实上,即使在具有真正私有属性的语言(如Java,它们被称为实例字段)中,通常也会使用某种形式的强大反射机制来绕过它,所以...

如果您这样做,需要考虑的一件事是,如果序列化,是否需要JSON中包含的私有属性。如果没有,只需实现toJSON,这样您就可以控制序列化期间包含哪些属性:

var obj = {
    _array: [],
    foo: "a value to include in JSON",
    set array(size) {
        this._array = [];          // Note the _
        for (var i = 0; i < size; i++) {
            this._array[i] = i;
        }
    },
    showArray() {
        console.log(this._array);
    },
    toJSON() {
        return {
            // Here we list only the properties we want to have
            // included in the JSON
            foo: this.foo
        };
    }
};
  
var myObj = Object.create(obj); 
myObj.array = 20; 
myObj.showArray();
console.log(JSON.stringify(myObj));

答案 1 :(得分:2)

在编写this.array = []时,您正在使用setter内部的setter。引入另一个名为_array的成员,并将其填入array属性的setter中。

var obj = {
  _array: [],
  set array(size) {
   for (var i = 0; i < size; i++){
      this._array[i] = i; 
   }
  }
};


var myObj = Object.create(obj); 
myObj.array = 20; 

答案 2 :(得分:0)

你曾提到你想使用setter和getter,这个片段只使用obj.array而不是showArray来查看对象的数组。

var obj = (function() {
    var _array = [];
    return {
        get array(){
            return _array;
        },
        set array(size) {
            _array = [];              
            for (var i = 0; i < size; i++) {
                _array[i] = i;       
            }
        }
    };
})();

obj = Object.create(obj);
obj.array = 20;
console.log(obj.array);