如何在JavaScript中创建受保护的对象属性

Dra*_*ara 12 javascript prototype-programming

是否有一个JavaScript模式模仿"受保护的"对象属性,就像你在C++这样的语言中看到的那样?

基本上,我想创建一个具有许多"受保护"对象属性的对象A,这些属性只能从对象A的原型中定义的方法访问.即 - 不能从A的非原型方法公开访问.

例如,理想情况是这样的:

function A(){
    var prop1 = 1;      
}

A.prototype.myFunc = function(){
    var newVar = this.prop1;   //newVar now is equivalent to 1
}

var instanceOfA = new A();
var newVar2 = instanceOfA.prop1;  //error given as prop1 is "protected"; hence undefined in this case
Run Code Online (Sandbox Code Playgroud)

BTW - 我不希望特权成员函数的模式访问私有属性,因为成员函数仍然是公共的.

jfr*_*d00 12

没有对象属性只能从原型方法访问A,而不能从非原型方法访问A.该语言没有这种类型的功能,我不知道任何解决方法/黑客实现它.

使用Doug Crockford的方法,您可以创建只能从预定义的非原型方法(构造函数中定义的方法)访问的成员属性.因此,如果您尝试仅限制对一组预定义方法的访问,则可以实现此目的.除此之外,我认为你运气不好.

如果您想要其他想法,如果您更多地了解您在代码中实际尝试完成的内容,而不仅仅是如何使用其他语言模拟某个功能,那么您可能会获得更多帮助.Javascript与C++有很大的不同,最好从问题的需要开始,而不是试图找到一些C++特性的类比.


Tho*_*ing 9

你不能在Javascript中做到这一点.

  • {{citation needed}} (5认同)
  • 这是事实,试图假装否则比接受这个简单事实更有害. (4认同)

Mar*_*tke 5

我找到了创建受保护成员的方法.因此,我调用基础构造函数并同时返回带有受保护成员的对象:

var protected = BaseClass.call(this); 
Run Code Online (Sandbox Code Playgroud)

这是一个例子:

function SignedIntegerArray(size)
{
    var public = this;
    var protected = {};

    // private property:
    var _maxSize = 10000;
    // protected property:
    protected.array = [];
    // public property:
    public.Length = size;

    if(!isInteger(size) || size < 0 || size > _maxSize) { throw "argument exception"; }
    for(var index = 0; index != size; index++) { protected.array[index] = 0; }

    // private method:
    function isInteger(i) { return i == i + 0 && i == ~~i; }
    // protected method:
    protected.checkIndex = function(index) { return index >= 0 && index < size; }
    // public methods:
    public.SetValue = function(index, value) { if(protected.checkIndex(index) && isInteger(value)) { protected.array[index] = value; } };
    public.GetValue = function(index) { if(protected.checkIndex(index)) { return protected.array[index]; } else { throw "index out of range exception"; }}

    return protected;
}

function FloatArray(size, range)
{
    var public = this;
    var protected = SignedIntegerArray.call(this, size); // call the base constructor and get the protected members 

    // new private method, "isInteger" is hidden...
    function isFloat(argument) { return argument != ~~argument; }
    // ...but "checkIndex" is accessible
    public.SetValue = function(index, value) { if(protected.checkIndex(index) && isFloat(value) && value >= public.MinValue && value <= public.MaxValue) { protected.array[index] = value; } };

    // new public properties:
    public.MinValue = -range;
    public.MaxValue = range;

    return protected; // for sub-classes
}

function newObject(className, args) { return new function() { className.apply(this, args)}} // you need to use function.call or function.apply to initialize an object. otherwise the protected-object is empty.
window.addEventListener("load", function()
{
    var o = newObject(FloatArray, [4, 50.0]);
    o.SetValue(3, 2.1);
    console.log(o.GetValue(3));
    console.log(o.Length); // property from the base-class
});
Run Code Online (Sandbox Code Playgroud)