Javascript属性最终在循环中

时间:2017-11-14 13:54:55

标签: javascript loops object properties

以下代码将添加属性' id'到对象' obj'。调用getter和setter时会有一个console.log执行。



let obj = {}

Object.defineProperty(obj, 'id', {
    set: (val) => { console.log('set'); this.id = val; },
    get: () => { console.log('get'); return this.id; }
})

obj.id = 1;
// 'set'
console.log(obj.id);
// 'get'
// 1




我想为构造函数添加相同的功能,但它最终会循环。



let myObject = function(){
    Object.defineProperty(this, 'id', {
        set: (val) => { console.log('set'); this.id = val; },
        get: () => { console.log('get'); return this.id; }
    })
}

let obj = new myObject();
obj.id = 1;
// 'set'
// 'set'
// 'set'
// ...
// error
console.log(obj.id);




如何解决而不创建伪私有变量这个问题' _id'?

顺便说一下,在使用类时遇到同样的问题。

2 个答案:

答案 0 :(得分:0)

这有点奇怪,但似乎setter开始以递归方式调用自身,因此代码进入无限循环的setter调用,然后表示超出了最大调用堆栈大小。我可以提出一个解决方案:在创建的实例上定义setter和getter。这样它也有效:

let myObject = function(){

}

let obj = new myObject();

Object.defineProperty(obj, 'id', {
        set: (val) => { console.log('set'); this.id = val; },
        get: () => { console.log('get'); return this.id; }
    })

obj.id = 1;
console.log(obj.id);

<强> UPD:

您还可以创建一些工厂函数,它将自动添加id属性实例:

function objectFactory (num) {

    let myObject = function(){

    };

    let instance = new myObject();

    Object.defineProperty(instance, 'id', {
        set: (val) => { console.log('set ' + num); this.id = val; },
        get: () => { console.log('get ' + num); return this.id; }
    });

    return instance;
}


let obj = objectFactory(1);
let obj1 = objectFactory(2);
let obj2 = objectFactory(3);

obj.id = 1;
obj1.id = 1;
obj2.id = 1;

console.log(obj.id);
console.log(obj1.id);
console.log(obj2.id);

答案 1 :(得分:0)

我想我找到了答案。只要您引用_id而不是this._id,就不会在对象本身中存储任何值。

let myObj = function(){
    let _id
    Object.defineProperty(this, 'id', {
        get: () => {console.log('get'); return _id},
        set: (val) => {console.log('set'); _id = val}
    })
}

let obj = new myObj()

obj.id = 1
// -> 'set'

console.log(obj.id)
// -> 'get'
// -> 1

console.log(obj)
// -> {}
// the _id variable will not be part of the object!