通常你需要 class 方法。 @Raynos 在 2011 年 5 月 7 日的回答完成了工作,但它定义了 instance 方法,而不是类方法。
下面说明了一个类定义,其中 getter 和 setter 是类的一部分。这个定义很像@Raynos 的答案,但在代码中有两个不同之处:(1)“defineProperties()”动作已从构造函数中移出。 (2) “defineProperties()”的参数由实例对象“this”改为构造函数的原型对象。
function TheConstructor(side) {
this.side = side;
}
Object.defineProperties(TheConstructor.prototype, {
area: {
get: function() { return this.side * this.side; }
,set: function(val) { this.side = Math.sqrt(val); }
}
});
// Test code:
var anInstance = new TheConstructor(2);
console.log("initial Area:"+anInstance.area);
anInstance.area = 9;
console.log("modified Area:"+anInstance.area);
这会产生这些结果:
initial Area:4
modified Area:9
虽然通常是类与实例之间的区别
定义只是风格问题,有目的
良好的风格,并且在某些情况下区分很重要:
memoized getter。 memoized getter 的目的是
此处描述:Smart/self-overwriting/lazy getters
在类级别定义getter,当memoized值是
与整个班级有关。例如,一个配置文件
应该只读一次;然后应应用结果值
在节目期间。以下示例代码
在类级别定义一个 memoized getter。
function configureMe() {
return 42;
}
Object.defineProperties(TheConstructor.prototype, {
memoizedConfigParam: {
get: function() {
delete TheConstructor.prototype.memoizedConfigParam;
return TheConstructor.prototype.memoizedConfigParam = configureMe();
}
,configurable: true
}
});
// Test code:
console.log("memoizedConfigParam:"+anInstance.memoizedConfigParam);
生产:
memoizedConfigParam:42
从示例中可以看出,memoized getter 具有
getter 函数删除自身的特征,
然后用一个简单的值替换自己
(大概)永远不会改变。
请注意,“configurable”必须设置为“true”。
当memoized值时,在实例级别定义getter
取决于实例的内容。定义移动
在构造函数内部,关注的对象是'this'。
function TheConstructorI(side) {
this.side = side;
Object.defineProperties(this, {
memoizedCalculation: {
get: function() {
delete this.memoizedCalculation;
return this.memoizedCalculation = this.expensiveOperation();
}
,configurable: true
}
});
}
TheConstructorI.prototype.expensiveOperation = function() {
return this.side * this.side * this.side;
}
//Test code:
var instance2 = new TheConstructorI(2);
var instance3 = new TheConstructorI(3);
console.log("memoizedCalculation 2:"+instance2.memoizedCalculation);
console.log("memoizedCalculation 3:"+instance3.memoizedCalculation);
生产:
memoizedCalculation 2:8
memoizedCalculation 3:27
如果你想保证(而不是假设)记忆
值永远不会改变,“可写”属性需要
被改变。这使得代码有点复杂。
function TheConstructorJ(side) {
this.side = side;
Object.defineProperties(this, {
memoizedCalculation: {
get: function() {
delete this.memoizedCalculation;
Object.defineProperty( this, 'memoizedCalculation'
,{ value : this.expensiveOperation()
,writable : false
});
return this.memoizedCalculation;
}
,configurable: true
}
});
}
TheConstructorJ.prototype.expensiveOperation = function() {
return this.side * this.side * this.side;
}
//Test code:
var instanceJ = new TheConstructorJ(2);
console.log("memoizedCalculation:"+instanceJ.memoizedCalculation);
instanceJ.memoizedCalculation = 42; // results in error
生产:
memoizedCalculation:8
>Uncaught TypeError: Cannot assign to read only property 'memoizedCalculation' of object '#<TheConstructorJ>'
从 2011 年 3 月 7 日起,OP 的原始问题提出了基本的
getter 和 setter 语法,注意到它在一个对象上工作,但是
不在'this'上,并询问如何在其中定义getter和setter
一个构造函数。除了上面所有的例子,还有
也是一种“廉价”的做法:在其中创建一个新对象
构造函数,就像 OP 所做的那样,但随后将对象分配给
成为“this”中的成员。所以,原始代码看起来像
这个:
var MyClass = function(value) {
var test = !!value; // 'test' has to be a boolean
this.data = {
get test() { return test },
set test(value) { test = !!value }
};
};
var instance = new MyClass(true);
// But now 'data' is part of the access path
instance.data.test = 0;
console.log(instance.data.test);
生产:
false
信不信由你,我实际上遇到过这样的情况
这种“廉价”是最好的解决方案。具体来说,我用这个
当我将几个表中的记录封装在其中时的技术
一个单一的类,并希望呈现一个统一的视图,好像
它们是一条称为“数据”的记录。
玩得开心。
IAM_AL_X