我在JavaScript中编写了一个简单的class
(想要更好的词)。该类创建了两个名为foo
和bar
的访问者(获取/设置)属性,以及两个名为setProperty
和getProperty
的方法。
属性的get / set方法调用getProperty
和setProperty
,后者又从属性对象中获取和设置属性。
我希望在这里看到无限递归,其中属性调用方法,这些方法调用属性,这些属性调用方法......等等。
但是它有效...而且我很清楚如何以及存储值的位置!
示例代码
var Test = (function () {
return function Test() {
var $this = this,
properties = {
foo: {
get: function () { return $this.getProperty("foo"); },
set: function (value) { $this.setProperty("foo", value); },
enumerable: false,
configurable: false
},
bar: {
get: function () { return $this.getProperty("bar"); },
set: function (value) { $this.setProperty("bar", value); },
enumerable: false,
configurable: false
}
};
Object.defineProperties(this, properties);
this.getProperty = function (name) {
console.log("get was definitely called!");
return properties[name];
};
this.setProperty = function (name, value) {
console.log("set was definitely called!");
properties[name] = value;
};
};
})();
var test = new Test();
//undefined
test.foo = "Hello World";
//set was definitely called!
//"Hello World"
test.bar = 3;
//set was definitely called!
//3
test.foo;
//get was definitely called!
//"Hello World"
test.bar;
//get was definitely called!
//3
非常有兴趣知道为什么我不只是收到“太多的递归”错误!
答案 0 :(得分:2)
当您致电defineProperties
时,您正在test
对象中创建属性,而不是properties
对象中的属性。
properties
对象不再用作属性,仅作为属性值的存储重用。设置foo
属性将使用值替换property
对象中的属性定义。
设置test.foo
属性时,将调用属性的setter代码并将值存储在properties
对象中,但这不会影响test.foo
属性。创建属性后,不再使用用于定义它们的对象。
代码有点令人困惑,因为它首先使用properties
对象作为属性的定义,然后重用它来存储属性值。如果为此使用两个单独的对象,则更清楚的是设置属性不会影响属性本身:
var Test = (function () {
return function Test() {
var $this = this,
def = {
foo: {
get: function () { return $this.getProperty("foo"); },
set: function (value) { $this.setProperty("foo", value); },
enumerable: false,
configurable: false
},
bar: {
get: function () { return $this.getProperty("bar"); },
set: function (value) { $this.setProperty("bar", value); },
enumerable: false,
configurable: false
}
},
storage = {};
Object.defineProperties(this, def);
this.getProperty = function (name) {
console.log("get was definitely called!");
return storage[name];
};
this.setProperty = function (name, value) {
console.log("set was definitely called!");
storage[name] = value;
};
};
})();