How to Create Protected Object Properties in JavaScript

前端 未结 8 1963
梦毁少年i
梦毁少年i 2020-12-10 04:49

Is there a JavaScript pattern which mimics \"Protected\" object properties like what you see in languages like C++ ??

Basically, I\'d like to create an Object A whic

8条回答
  •  一个人的身影
    2020-12-10 05:25

    I was interested to find a way to answer your question, and here's what I was able to do.

    You'll need this helper:

    var ProtectedHandler = (function () {
        /// 
        /// Tool to handle the protected members of each inheritance.
        /// 
        /// Current protected variable.
        /// The arguments variable of the object.
        /// The function to initialise the variable in the 'object'.
        /// Is this the ultimate base object.
        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;
    })();
    

    This helper will allow you to handle multiple inheritances. The trick is to copy the protected variable from the base object to your new object (child).

    To prove you it's working, here's an example:

    // 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);
    

    And here's the tests:

    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"
    

提交回复
热议问题