gpt4 book ai didi

javascript - 做一个对外只读的属性,但是我的方法还是可以设置的

转载 作者:可可西里 更新时间:2023-11-01 02:06:19 27 4
gpt4 key购买 nike

在 JavaScript (ES5+) 中,我试图实现以下场景:

  1. 一个对象(其中将有许多单独的实例)每个都具有只读属性 .size 可以通过直接属性读取从外部读取,但不能从外部设置.
  2. .size 属性必须通过原型(prototype)上的某些方法进行维护/更新(并且应该保留在原型(prototype)上)。
  3. 我的 API 已经由规范定义,所以我不能修改它(我正在为一个已经定义的 ES6 对象开发一个 polyfill)。
  4. 我主要是想防止人们不小心开枪打自己的脚,而且真的不需要防弹只读(尽管越防弹越好),所以我愿意只要直接设置 obj.size = 3; 是不允许的,就可以妥协一些侧门访问属性。

我知道我可以使用在构造函数中声明的私有(private)变量并设置一个 getter 来读取它,但是我必须将需要维护该变量的方法从原型(prototype)中移出并在构造函数中声明它们也(因此他们可以访问包含变量的闭包)。对于这种特殊情况,我不想将我的方法从原型(prototype)中移除,所以我正在寻找其他可能的选择。

还有什么其他的想法(即使有一些妥协)?

最佳答案

好的,所以对于一个解决方案,您需要两个部分:

  • 一个size不可分配的属性,即 writable:true或者没有 setter属性
  • 一种改变size的值的方法反射(reflect),这不是.size = …它是公共(public)的,以便原型(prototype)方法可以调用它。

@plalx 已经提出了第二个“半私有(private)”的明显方式 _sizesize 的 setter/getter 反射(reflect)的属性.这可能是最简单、最直接的解决方案:

// declare
Object.defineProperty(MyObj.prototype, "size", {
get: function() { return this._size; }
});
// assign
instance._size = …;

另一种方法是制作 size属性不可写,但可配置,因此您必须使用 Object.defineProperty 的“长路” (尽管恕我直言,对于辅助函数来说甚至太短了)在其中设置一个值:

function MyObj() { // Constructor
// declare
Object.defineProperty(this, "size", {
writable: false, enumerable: true, configurable: true
});
}
// assign
Object.defineProperty(instance, "size", {value:…});

这两种方法绝对足以防止“搬起石头砸自己的脚”size = …作业。对于更复杂的方法,我们可能会构建一个公共(public)的、特定于实例的(闭包)setter 方法,该方法只能从原型(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 的自定义对象方法。

关于javascript - 做一个对外只读的属性,但是我的方法还是可以设置的,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23819730/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com