gpt4 book ai didi

javascript - 有没有一种简洁的方法可以在 JavaScript 中创建 'internal' 属性?

转载 作者:行者123 更新时间:2023-11-30 13:11:31 26 4
gpt4 key购买 nike

在 JavaScript 中,我可能会使用这样的顶级对象开始编写“库”或功能集合:

window.Lib = (function()
{
return {

// Define Lib here.
//

};

})();

我还可以在 Lib 中添加一些函数来创建与之相关的对象:

window.Lib = (function()
{
return {

ObjectA: function()
{
var _a = 5;

return {

getA: function(){ return _a; }

};

},


ObjectB: function()
{
var _b = 2;
var _c = 1;

return {

getB: function(){ return _b; }

};

}

};

})();

可以这样使用:

var thing = Lib.ObjectA();
var thing2 = Lib.ObjectA();
var thing3 = Lib.ObjectB();

我可以使用上面创建的每个方法中的方法来获取 ObjectA()_b 中定义的 _a 的值在 ObjectB() 中:

alert(thing.getA()); // 5
alert(thing3.getB()); // 2

我想实现的是:

假设我想访问属性 _c(在 ObjectB() 中定义)但仅在 Lib 的范围内/强>。我该怎么办?我的意思是,我想让该属性在我在 Lib() 返回的对象中定义的任何函数中可读,但我不想在该函数之外公开这些值。

代码示例:

window.Lib = (function()
{
return {

ObjectA: function(){ ... },
ObjectB: function(){ ... },

assess: function(obj)
{
// Somehow get _c here.
alert( obj.getInternalC() );
}

};

})();

这会像这样工作:

var thing = Lib.ObjectB();
alert( thing.getInternalC() ) // error | null | no method named .getInternalC()

Lib.assess(thing); // 1

希望这是有道理的。

最佳答案

所以你想要每个实例保护的属性?也就是说,由 ObjectAObjectB 等创建的实例的属性,但它们可由您的库中的代码访问,并且不在外面编码?

您目前无法在 JavaScript 中正确地做到这一点,但您将能够在下一个版本中使用 private name objects . (不过,请参阅下面的“几乎可以做到”,了解您现在可以在 ES5 中做的类似事情。)

很容易创建由 Lib 中的所有代码共享的数据,但不是 per-instance 属性,如下所示:

window.Lib = (function()
{
var sharedData;

// ...
})();

其中定义的所有函数(您的 ObjectA 等)都可以访问那个 sharedData 变量,这是完全无法从外部访问的。但它不是每个实例,ObjectAObjectB 等创建的每个对象都没有自己的副本。

差不多了

如果您的代码将在 ES5 环境中运行(因此,任何现代浏览器,其中“现代”包括 IE8 或更早版本),您可以隐藏 但实际上不是私有(private)属性,通过 Object.defineProperty。这类似于私有(private)名称对象在 ES.next 中的工作方式,但不是真正私有(private)的:

Live Example | Source

window.Lib = (function() {
// Get a random name for our "c" property
var c = "__c" + Math.round(Math.random() * 1000000);

// Return our library functions
return {

ObjectA: function() {
// Create an object with a couple of public proprties:
var obj = {
pub1: "I'm a public property",
pub2: "So am I"
};

// Add our obscured "c" property to it, make sure it's
// non-enumerable (doesn't show up in for-in loops)
Object.defineProperty(obj, c, {
enumerable: false, // false is actually the default value, just emphasizing
writable: true,
value: "I'm an obscured property"
});

// Return it
return obj;
},

ObjectB: function(){ /* ... */ },

assess: function(obj) {
// Here, we access the property using the `c` variable, which
// contains the property name. In JavaScript, you can access
// properties either using dotted notation and a literal
// (`foo.propName`), or using bracketed notation and a string
// (`foo["propName"]`). Here we're using bracketed notation,
// and our `c` string, which has the actual property name.
display( obj[c] );
},


alter: function(obj, value) {
// Similarly, we can change the value with code that has
// access to the `c` variable
obj[c] = value;
}
};
})();

然后像这样使用它:

// Create our object
var o = Lib.ObjectA();

// Play with it
display("pub1: " + o.pub1); // displays "pub1: I'm a public property"
display("c: " + o.c); // displays "c: undefined" since `o` has no property called `c`
Lib.assess(o); // displays "I'm an obscured property"

// Note that our obscured property doesn't show up in for-in loops or Object.keys:
var propName, propNames = [];
for (propName in o) {
propNames.push(propName);
}
display("propNames: " + propNames.join(","));
display("Object.keys: " + Object.keys(o).join(","));

// Our Lib code can modify the property
Lib.alter(o, "Updated obscured property");
Lib.assess(o);

Lib.ObjectA 返回的对象有一个属性,每次加载 Lib 时其名称都会改变,并且不可枚举(不显示在 for-in 循环)。获取它的唯一方法是知道它的名称(同样,每次创建 Lib 时名称都会改变——例如,每次加载页面)。 Lib 中的代码知道属性名称是什么,因为它在所有 Lib 代码共享的 c 变量中。由于您可以使用方括号表示法和字符串访问属性,我们可以使用 instance[c] 来访问该属性。

您会看到这些是如何被很好地遮盖的。 Lib 之外的代码在枚举对象中的属性时看不到被隐藏的属性,它们不知道我们分配给它的半随机名称,因此无法找到该属性。当然,您可以使用调试器通过检查找到它,但调试器可以做很多事情。

事实上,这就是私有(private)属性在 ES.next 中的工作方式,除了 c 不是字符串,它将是私有(private)名称对象。

关于javascript - 有没有一种简洁的方法可以在 JavaScript 中创建 'internal' 属性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13723950/

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