如何使用Prototype库模拟JavaScript中的访问修饰符? [英] How do I mimic access modifiers in JavaScript with the Prototype library?

查看:130
本文介绍了如何使用Prototype库模拟JavaScript中的访问修饰符?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在使用原型库一段时间,偶尔发现自己希望我有多个访问级别(公共,私有和受保护)。到目前为止我最接近的是:

I've been working with the prototype library for some time now and occasionally find myself wishing I had multiple access levels (public, private, and protected). The closest I've come so far is the following:

SampleBase = Class.create({
    /* virtual public constructor */
    initialize: function(arg1, arg2)
    {
        // private variables
        var privateVar1, privateVar2;

        // private methods
        var privateMethod1 = function() { }
        function privateMethod2() { }

        // public (non virtual) methods
        this.publicNonVirtual1 = function() { return privateVar1; }
        this.publicNonVirtual2 = function() { return privateVar2; }
    },
    // public methods (that cannot access privates)
    publicVirtual1: function() { /* Cannot access privates here. */ },
    publicVirtual2: function() { /* Cannot access privates here. */ }
});

由于以下几个原因,这不太理想:

This less then ideal for several reasons:


  • 没有受保护的级别

  • 我可以让公共成员访问可以被覆盖的私有成员或公共成员,但不能访问可以访问私有成员的公共成员

  • 我可以覆盖的公共方法不是原型。

I已经做了一些搜索,但没有找到任何暗示我可以做得更好而不改变原型如何工作的东西。以下是一些更有趣的链接:

I've done some searching but haven't found anything that suggests I can do better without altering how prototype works. Here's some of the more interesting links:

  • Using Prototype’s Class.create to define private/protected properties and methods
  • JavaScript private methods
  • Private Members in JavaScript
  • Again with the Module Pattern – reveal something to the world

我看过它的建议您可以通过执行以下操作为我的公共虚拟方法提供访问器:

I've seen it suggested that you can provide accessors for my public virtual methods to use by doing something like this:

Message = Class.create({
    initialize: function(message)
    {
        var _message = message;
        this.getMessage = function() { return _message; }
        this.setMessage = function(value) { _message = value; }
    },
    printMessage: function() { console.log(this.getMessage()); },
    appendToMessage: function(value) { this.setMessage(this.getMessage() + value); }
});

这显然不会按预期工作。目标是仅允许从对象外部打印和附加消息。为使虚拟公共功能工作而提供的setter也允许完全控制消息。可以将其更改为使虚拟方法更像shell,如下所示:

This clearly will not work as intended. The goal is to only allow printing and appending to the message from outside of the object. The setter provided to make the virtual public function work also allows full control of the message. It could be changed to make the virtual method little more then a shell as follows:

Message = Class.create({
    initialize: function(message)
    {
        var _message = message;
        this._printMessage = function() { console.log(_message); }
        this._appendToMessage = function(value) { _message += value; }
    },
    printMessage: function() {this._printMessage(); },
    appendToMessage: function(value) { this._appendToMessage(value); }
});

这个新版本确实限制了这个类的公共访问,但有些多余。更不用说如果在子类中覆盖appendToMessage,第三方仍然可以调用_appendToMessage来访问不合适的原始方法。

This new version does limit public access for this class but is somewhat redundant. Not to mention if appendToMessage is overriden in a subclass a third party can still call _appendToMessage to access the original method which is not good.

我确实有非常肮脏的想法会让我接近,但是我可能不会打开一堆蠕虫。我可以稍后发布,但同时有人建议将两种类型的公共方法合并为一种有用的类型或如何实现受保护的成员。

I do have a very dirty idea that will get me close but is a can of worms I'd rather not open. I may post it later but in the mean time does anyone have suggestions for merging the two types of public methods into one useful type or on how to implement protected members.

编辑:
我怀疑缺乏反馈(除了 bobince 之外不打扰评论)意味着我我是正确的,因为你不能再把它拿走了,但我想我会澄清一点以防万一。我认为不可能得到任何接近其他语言保护的东西。我更感兴趣的是知道限制的位置以及我对所涉及原理的理解有多准确。但我认为,如果我们可以使各种保护级别运行到非公共成员不会出现在for ... in循环中(或者在Prototypes Object.keys中,那么它将是有趣的,如果没有用的话)。即使知道他们正在做什么的人仍然可以通过修补我的原型等方法来破坏规则。毕竟,它像 bobince 所说他们没有人应该责怪自己

I suspect the lack of feedback (aside from bobince's don't bother comment) mean that I am correct in that you can't take it any farther but I think I'll clarify a little just in case. I don't think it is possible to get anything close to the protection of other languages. I'm more interested in knowing where the limits lie and how accurate my understanding of the principles involved are. I do however think it would be interesting, if not useful, if we could get the various protection levels functioning to the point that non public members don't show up in a for...in loop (or in Prototypes Object.keys which uses for..in) even if it people who know what they are doing can still break the rules by doing things like tinkering with my prototypes. Afterall, its like bobince says " they have no-one to blame but themselves"

现在就 bobince 提出的问题发表评论:

Now to comment on an issue raised by bobince:


即使您创建了真正的
私有/受保护变量,它仍然是
不会为您提供完整的
封装有效安全
边界需要。 JavaScript的
能够摆弄原型
的内置类型你的方法将是
使用给攻击者提供
破坏方法的能力。

Even if you made real private/protected variables it still wouldn't get you the full encapsulation an effective security boundary would require. JavaScript's ability to fiddle with the prototypes of built-in types your methods will be using gives an attacker the ability to sabotage the methods.

这是我理解的一个限制,我可能应该在上面提到过。但是,从保护我的代码免受试图破解它的人的角度来看,我不是在考虑这个问题。但是,我确实有一些值得注意的事情(或者如果我错了就需要纠正):

This is one limitation I do understand and I probably should have mentioned above. However, I am not looking at this from the point of view of protecting my code from someone trying to "hack" it. However, I do have a few things that may be worth noting (or in need of correcting if I am wrong):


  • 只有我的公众会员以这种方式容易受到攻击。

  • 如果我的公共虚拟方法以这种方式被泄露,那么被入侵的方法仍然无法访问私有成员。

  • 如果我的公共(非虚拟)成员以这种方式被泄露,那么,与该方法的原始版本不同,受损版本将无法访问私人成员。

  • 据我所知,通过initialize方法之外定义的方法访问私有成员的唯一方法是利用某些浏览器处理eval调用的方式中的错误。

  • Only my public members are vulnerable in this way.
  • If my public virtual methods are "compromised" in this way, then the "compromised" methods will still not have access to the private members.
  • If my public (non virtual) members are "compromised" in this way, then, unlike the original version of the method, the "compromised" version will not have access to the private memebers.
  • As far as i know the only way to gain accesses to the private members by methods defined outside of initialize method is too take advantage of a bug in the way some browsers handle eval calls.

推荐答案

如何在JavaScript中创建受保护的成员:在名称的开头加上下划线。

How to make a protected member in JavaScript: put an underscore at the start of the name.

说真的,你不会在JS脚本中拥有安全边界ld需要真正适当的保护。访问级别是trad-OO编码器的痴迷,在Web脚本编写环境中没有任何意义。即使您制作了真正的私有/受保护变量,它仍然无法为您提供有效安全边界所需的完整封装。 JavaScript能够使用你的方法将使用的内置类型的原型,使攻击者能够破坏这些方法。

Seriously, you're not going to have security boundaries within a JS script that would make real proper protection necessary. Access levels are a trad-OO coder's obsession that make no sense in the context of web scripting. Even if you made real private/protected variables it still wouldn't get you the full encapsulation an effective security boundary would require. JavaScript's ability to fiddle with the prototypes of built-in types your methods will be using gives an attacker the ability to sabotage the methods.

所以不要打扰试试。就像Pythoners那样做:将方法标记为外人不应该调用的东西,并完成它。如果有人使用你的代码并依赖于名字开头的 _ 的成员,那就是他们的问题,他们没有人责备他们自己的脚本中断了。同时,你可以通过不拥有严格的私有和受保护成员来使开发和调试阶段更容易。

So don't bother try. Just do like the Pythoners do: flag the method as something outsiders shouldn't be calling, and be done with it. If someone uses your code and relies on a member with _ at the start of the name, that's their problem and they have no-one to blame but themselves when their script breaks. Meanwhile you'll make the development and debugging stages easier for yourself by not having strict private and protected members.

然后你可以选择per-instance-members(用于回调绑定)方便)或原型成员(为了提高效率),无论你是否打算将它们变为私人,你都不会因为不一致而惹恼自己。

Then you can choose per-instance-members (for callback binding convenience) or prototyped members (for efficiency), whether or not you intend them to be private, and you won't trip yourself up on the inconsistency.

这篇关于如何使用Prototype库模拟JavaScript中的访问修饰符?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆