Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/amazon-web-services/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在JavaScript中创建受保护的对象属性 有一个JavaScript模式,模仿“保护”对象属性,如C++语言?_Javascript_Prototype Programming - Fatal编程技术网

如何在JavaScript中创建受保护的对象属性 有一个JavaScript模式,模仿“保护”对象属性,如C++语言?

如何在JavaScript中创建受保护的对象属性 有一个JavaScript模式,模仿“保护”对象属性,如C++语言?,javascript,prototype-programming,Javascript,Prototype Programming,基本上,我想创建一个对象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(); v

基本上,我想创建一个对象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

顺便说一句-我不希望特权成员函数访问私有属性的模式,因为成员函数仍然是公共的。

这可能就是您要寻找的:

您不能在Javascript中进行访问。

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

使用,可以创建只能从预定义的非原型方法(构造函数中定义的方法)访问的成员属性。因此,如果您试图将访问权限限制在预定义的一组方法上,这将实现这一点。除此之外,我认为你运气不好


如果您想要其他想法,那么如果您更多地描述您在代码中实际试图实现的目标,而不仅仅是如何用另一种语言模拟某个特性,您可能会得到更多的帮助。JavaScript与C++相比有很大的不同,最好是从问题的需要出发,而不是试图找到一些C++特性的类比。

< P>看看MKS在他的网站上提出的解决方案:


它模拟受保护对象的方法和属性的访问级别。

我找到了一种创建受保护成员的方法。因此,我调用基本构造函数,同时返回一个包含受保护成员的对象:

var protected = BaseClass.call(this); 
这里有一个例子:

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
});
// That's the default extends function from typescript (ref: http://www.typescriptlang.org/)
var __extends = this.__extends || function (d, b) {
    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
    function __() { this.constructor = d; }
    __.prototype = b.prototype;
    d.prototype = new __();
};

var BaseClass = (function () {        
    function BaseClass() {
        // Members
        var private = {},
            protected = {},
            public = this;

        // Constructor
        ProtectedHandler.handle(protected, arguments, function () {
            protected.type = "BaseClass";
        }, true);

        // Methods
        protected.saySomething = function () {
            return "Hello World";
        };

        public.getType = function () {
            return protected.type;
        };
    }

    return BaseClass;
})();



var Person = (function (_super) {
    __extends(Person, _super);

    function Person(name) {
        // Members
        var private = {},
            protected = {},
            public;

        // Constructor
        _super.call(public = this, ProtectedHandler.handle(protected, arguments, function (p) {
            protected = p; //This is required to copy the object from its base object.
            protected.name = name;
            protected.type = "Person";
        }));

        //Method
        public.getName = function () {
            return protected.name;
        };

        public.saySomething = function () {
            return protected.saySomething();
        };
    }
    return Person;
})(BaseClass);


var Child = (function (_super) {
    __extends(Child, _super);

    function Child(name) {
        // Members
        var private = {},
            protected = {},
            public;

        // Constructor
        _super.call(public = this, name, ProtectedHandler.handle(protected, arguments, function (p) {
            protected = p; //This is required to copy the object from its base object.
            protected.type = "Child";
        }));

        //Method
        public.setName = function (value) {
            return protected.name = value;
        };
    }
    return Child;
})(Person);
函数签名集成阵列(大小)
{
var public=this;
var-protected={};
//私人财产:
var_maxSize=10000;
//受保护财产:
protected.array=[];
//公共财产:
公共。长度=大小;
如果(!isInteger(size)| | size<0 | | size>_maxSize){抛出“参数异常”;}
对于(var index=0;index!=size;index++){protected.array[index]=0;}
//私人方法:
函数isInteger(i){返回i==i+0&&i==i;}
//保护方法:
protected.checkIndex=函数(index){return index>=0&&indexpublic.SetValue=function(index,value){if(protected.checkIndex(index)&&isFloat(value)&&value>=public.MinValue&&value我很想找到一种方法来回答你的问题,下面是我能做的

您将需要此帮助程序:

var ProtectedHandler = (function () {
    /// <Sumarry>
    /// Tool to handle the protected members of each inheritance.
    /// </Summary>
    /// <param name="current">Current protected variable.</param>
    /// <param name="args">The arguments variable of the object.</param>
    /// <param name="callback">The function to initialise the variable in the 'object'.</param>
    /// <param name="isParent">Is this the ultimate base object.</param>
    function ProtectedHandler(current, args, callback, isParent) {
        this.child = getChild(args);
        if (callback)
            this.callback = callback;

        if (isParent)
            this.overrideChild(current);
    }

    // Get the ProtectedHandler from the arguments
    var getChild = function (args) {
        var child = null;
        if (args.length > 0 && (child = args[args.length - 1]) && child.constructor === ProtectedHandler)
            return child;
    };

    // Chain Initialise the protected variable of the object and its inheritances.
    ProtectedHandler.prototype.overrideChild = function (newValue) {
        if (this.callback != null) {
            this.callback(newValue);
        }
        if (this.child != null) {
            this.child.overrideChild(newValue);
        }
    };

    // Static function to create a new instance of the protectedHandler object.
    ProtectedHandler.handle = function (protected, arguments, callback, isParent) {
        return new ProtectedHandler(protected, arguments, callback, isParent);
    };

    return ProtectedHandler;
})();
以下是测试:

var testBase = new BaseClass();
testBase.getType(); //"BaseClass"
testBase.saySomething; //undefined

var testPerson = new Person("Nic");
testPerson.getType(); //"Person"
testPerson.saySomething(); //"Hello World"
testPerson.name; //undefined
testPerson.getName() //"Nic"
testPerson.setName; //undefined

var testChild = new Child("Bob");
testChild.getType(); //"Child"
testChild.saySomething(); //"Hello World"
testChild.name; //undefined
testChild.getName(); //"Bob"
testChild.setName("George");
testChild.getName(); //"George"

我喜欢的一种模式与大多数语言中受保护访问的工作方式不同,但提供了类似的好处

基本上,使用生成器方法为属性创建闭包,然后让该方法创建具有自由访问权限的“完整”对象以及具有更有限访问权限的“公开”对象。将公开对象放入完整对象的属性中,并将该完整对象返回给调用者

然后,调用方可以使用完整对象(并将其传递给其他适当的协作者),但只将公开的对象提供给应该具有更严格访问权限的协作者

一个人为的例子

// Ring employs a typical private/public pattern while
// RingEntry employs a private/exposed/full access pattern.

function buildRing( size ) {
  var i
    , head = buildRingEntry( 0 )
    , newEntry;
  ;
  head.setNext( head );
  for( i = size - 1; i ; i-- ) {
    newEntry = buildRingEntry( i );
    newEntry.setNext( head.getNext() );
    head.setNext( newEntry );
  }
  function getHead() { return head.exposed; }
  return {
      getHead : getHead
  }
}

function buildRingEntry( index ) {
  var next
    , exposed
  ;
  function getIndex() { return index; }
  function setNext( newNext ) { next = newNext; }
  function getNextFullEntry() { return next; }
  function getNextExposedEntry() { return next.exposed; }
  exposed = {
      getIndex : getIndex
    , getNext  : getNextExposedEntry
  };
  return {
      getIndex : getIndex
    , setNext  : setNext
    , getNext  : getNextFullEntry
    , exposed  : exposed
  };
}
如果我们用它来构建一个由4个条目组成的环,
ring=buildRing(4);
,那么
ring.getHead().getIndex()给我们0,
ring.getHead().getNext().getIndex()给我们1,
ring.getHead().getNext().getNext().getIndex()给我们2,等等

但是,如果尝试执行
ring.getHead().setNext({})
ring.getHead().getNext().setNext({})
,则会出现错误,因为
setNext
不是公开条目对象的属性

警告:


由于这是在为每个新对象重新构建新闭包中的方法的模式家族中,因此它不适用于可能需要大量实例化的情况。

我的建议通常是不要强制查看JavaScript。闭包等可以实现某些功能,但语言不是设计的这将使你的代码更加复杂。相反,将你的方法正确地记录为私有或公共的,如果其他开发人员不遵循你的规范,这是他们的问题。顺便说一句,原型对象可以被扩充(它们不是密封的)-没有什么可以阻止入侵者向prototype对象添加新方法。因此,仅通过prototype方法访问属性并不安全(即使可能)JavaScript不是面向类的,它是面向对象的——不是面向对象的,而是指类实例,而是在……对象的意义上。没有像通常的类成员关键字在java或C++中的特性,而是需要基于语言的对象和事件驱动性质来设计实现。是基于ES6中新特性的解决方案。例如,请参见此处:我同意。Doug Crockford的文章是
// Ring employs a typical private/public pattern while
// RingEntry employs a private/exposed/full access pattern.

function buildRing( size ) {
  var i
    , head = buildRingEntry( 0 )
    , newEntry;
  ;
  head.setNext( head );
  for( i = size - 1; i ; i-- ) {
    newEntry = buildRingEntry( i );
    newEntry.setNext( head.getNext() );
    head.setNext( newEntry );
  }
  function getHead() { return head.exposed; }
  return {
      getHead : getHead
  }
}

function buildRingEntry( index ) {
  var next
    , exposed
  ;
  function getIndex() { return index; }
  function setNext( newNext ) { next = newNext; }
  function getNextFullEntry() { return next; }
  function getNextExposedEntry() { return next.exposed; }
  exposed = {
      getIndex : getIndex
    , getNext  : getNextExposedEntry
  };
  return {
      getIndex : getIndex
    , setNext  : setNext
    , getNext  : getNextFullEntry
    , exposed  : exposed
  };
}