Accessing private member variables from prototype-defined functions

前端 未结 25 860
孤城傲影
孤城傲影 2020-11-22 14:48

Is there any way to make “private” variables (those defined in the constructor), available to prototype-defined methods?

TestClass = function(){
    var priv         


        
相关标签:
25条回答
  • 2020-11-22 15:45

    Here's something I've come up with while trying to find most simple solution for this problem, perhaps it could be useful to someone. I'm new to javascript, so there might well be some issues with the code.

    // pseudo-class definition scope
    (function () {
    
        // this is used to identify 'friend' functions defined within this scope,
        // while not being able to forge valid parameter for GetContext() 
        // to gain 'private' access from outside
        var _scope = new (function () { })();
        // -----------------------------------------------------------------
    
        // pseudo-class definition
        this.Something = function (x) {
    
            // 'private' members are wrapped into context object,
            // it can be also created with a function
            var _ctx = Object.seal({
    
                // actual private members
                Name: null,
                Number: null,
    
                Somefunc: function () {
                    console.log('Something(' + this.Name + ').Somefunc(): number = ' + this.Number);
                }
            });
            // -----------------------------------------------------------------
    
            // function below needs to be defined in every class
            // to allow limited access from prototype
            this.GetContext = function (scope) {
    
                if (scope !== _scope) throw 'access';
                return _ctx;
            }
            // -----------------------------------------------------------------
    
            {
                // initialization code, if any
                _ctx.Name = (x !== 'undefined') ? x : 'default';
                _ctx.Number = 0;
    
                Object.freeze(this);
            }
        }
        // -----------------------------------------------------------------
    
        // prototype is defined only once
        this.Something.prototype = Object.freeze({
    
            // public accessors for 'private' field
            get Number() { return this.GetContext(_scope).Number; },
            set Number(v) { this.GetContext(_scope).Number = v; },
    
            // public function making use of some private fields
            Test: function () {
    
                var _ctx = this.GetContext(_scope);
                // access 'private' field
                console.log('Something(' + _ctx.Name + ').Test(): ' + _ctx.Number);
                // call 'private' func
                _ctx.Somefunc();
            }
        });
        // -----------------------------------------------------------------
    
        // wrap is used to hide _scope value and group definitions
    }).call(this);
    
    function _A(cond) { if (cond !== true) throw new Error('assert failed'); }
    // -----------------------------------------------------------------
    
    function test_smth() {
    
        console.clear();
    
        var smth1 = new Something('first'),
          smth2 = new Something('second');
    
        //_A(false);
        _A(smth1.Test === smth2.Test);
    
        smth1.Number = 3;
        smth2.Number = 5;
        console.log('smth1.Number: ' + smth1.Number + ', smth2.Number: ' + smth2.Number);
    
        smth1.Number = 2;
        smth2.Number = 6;
    
        smth1.Test();
        smth2.Test();
    
        try {
            var ctx = smth1.GetContext();
        } catch (err) {
            console.log('error: ' + err);
        }
    }
    
    test_smth();
    
    0 讨论(0)
提交回复
热议问题