说,我有一个实现3D对象的对象类型,它具有四元数和3轴旋转属性:
Object.defineProperty(MyObject3D.prototype, 'rotation', {
...
});
Object.defineProperty(MyObject3D.prototype, 'quaternion', {
...
});
我想确保每次修改每个属性时,会自动重新计算另一个属性。显然,如果我同时设置这些属性的set方法,我将遇到无限循环。
到目前为止,我能看到的唯一方法是实际使用另一组类似于旋转和四元数的属性(可能是不可枚举的,用于更清洁的对象内省):
Object.defineProperty(MyObject3D.prototype, '_rotation', {
enumerable: false
});
Object.defineProperty(MyObject3D.prototype, '_quaternion', {
enumerable: false
});
Object.defineProperty(MyObject3D.prototype, 'rotation', {
get: function() {
return this._rotation;
},
set: function(r) {
this._rotation = r;
this._quaternion = rotation2quaternion(r);
}
});
Object.defineProperty(MyObject3D.prototype, 'quaternion', {
get: function() {
return this._rotation;
},
set: function(q) {
this._quaternion = q;
this._rotation= quaternion2rotation(q);
}
});
你能想出更好的方法吗?也许我错过了一些Object.defineProperty的功能,可以让它更干净,更短?
答案 0 :(得分:2)
不是简单地设置rotation
和quaternion
访问器属性,而是让它们成为数据属性然后定义setRotation
和setQuaternion
方法来改变它们不是更简单?例如:
function MyObject3D() {
...
}
MyObject3D.prototype.setRotation = function (r) {
this.quaternion = rotation2quaternion(r);
this.rotation = r
return this;
};
MyObject3D.prototype.setQuaternion = function (q) {
this.rotation = quaternion2rotation(q);
this.quaternion = q;
return this;
};
现在您可以正常访问.rotation
和.quaternion
。但是,要设置它们,请改用.setRotation
和.setQuaternion
。是的,它不安全,因为用户可以手动设置.rotation
和.quaternion
。但它有几个优点:
defineProperty
。this
。解决此问题的另一种方法是使用不可变对象。这是你在Haskell中做的方式。例如:
function MyObject3D(rotation, quaternion) {
this.quaternion = quaternion;
this.rotation = rotation;
Object.freeze(this);
}
MyObject3D.prototype.putRotation = function (r) {
return new MyObject3D(r, rotation2quaternion(r));
};
MyObject3D.prototype.putQuaternion = function (q) {
return new MyObject3D(quaternion2rotation(q), q);
};
如果您的构造函数中有一些初始化逻辑,那么您可以将其移动到智能构造函数中:
function createMyObject3D(r, q) {
// some initialization logic
return new MyObject3D(r, q);
}
因此,当您想要创建一个新对象时,使用createMyObject3D
,当您想要改变对象时,使用new MyObject3D
传递新值。以下方法的优点是:
唯一的缺点是它取决于旧版浏览器中可能不存在的Object.freeze
。然而,冻结对象是一个可选步骤,可以省略。