在JavaScript(ES5 +)中,我正在尝试实现以下方案:
.size
,可以通过直接属性读取从外部读取它,但不能从外部设置。 .size
属性。 obj.size = 3;
,就可以在侧门上访问该属性。 我知道我可以使用构造函数中声明的私有(private)变量并设置一个getter来读取它,但是我必须将需要维护该变量的方法移出原型(prototype),并在构造函数中声明它们(因此他们可以访问包含变量的闭包)。对于这种特殊情况,我宁愿不要将方法从原型(prototype)中删除,而是要寻找其他可能的选择。
还有什么其他想法(即使有一些妥协)?
最佳答案
好的,因此对于解决方案,您需要两个部分:
size
属性,即writable:true
或没有setter
属性size
反射(reflect)的值的方法,该值不是.size = …
且是公共(public)的,以便原型(prototype)方法可以调用它。 @plalx已经通过第二个“半私有(private)的”
_size
属性提供了一种明显的方式,该属性由size
的getter反射(reflect)出来。这可能是最简单,最直接的解决方案:// declare
Object.defineProperty(MyObj.prototype, "size", {
get: function() { return this._size; }
});
// assign
instance._size = …;
另一种方法是使
size
属性不可写,但可配置,以便您必须对Object.defineProperty
使用“很长的路要走”(尽管imho对于辅助函数来说太短了)才能在其中设置值:function MyObj() { // Constructor
// declare
Object.defineProperty(this, "size", {
writable: false, enumerable: true, configurable: true
});
}
// assign
Object.defineProperty(instance, "size", {value:…});
这两种方法绝对足以防止“脚踏实地”的
size = …
分配。对于更复杂的方法,我们可以构建一个公共(public)的,特定于实例的(关闭)设置方法,该方法只能从原型(prototype)模块作用域方法中调用。(function() { // module IEFE
// with privileged access to this helper function:
var settable = false;
function setSize(o, v) {
settable = true;
o.size = v;
settable = false;
}
function MyObj() { // Constructor
// declare
var size;
Object.defineProperty(this, "size", {
enumerable: true,
get: function() { return size; },
set: function(v) {
if (!settable) throw new Error("You're not allowed.");
size = v;
}
});
…
}
// assign
setSize(instance, …);
…
}());
只要没有泄漏对
settable
的封闭访问,这确实是故障安全的。还有一种类似的,流行的,简短的方法是使用对象的身份作为访问 token ,大致如下:// module IEFE with privileged access to this token:
var token = {};
// in the declaration (similar to the setter above)
this._setSize = function(key, v) {
if (key !== token) throw new Error("You're not allowed.");
size = v;
};
// assign
instance._setSize(token, …);
但是,此模式并不安全,因为有可能通过使用带有恶意
token
方法的自定义对象将带有赋值的代码应用于自定义对象来窃取_setSize
。