JavaScript private methods

前端 未结 30 1509
-上瘾入骨i
-上瘾入骨i 2020-11-22 08:16

To make a JavaScript class with a public method I\'d do something like:

function Restaurant() {}

Restaurant.prototype.buy_food = function(){
   // something         


        
相关标签:
30条回答
  • 2020-11-22 09:02

    In these situations when you have a public API, and you would like private and public methods/properties, I always use the Module Pattern. This pattern was made popular within the YUI library, and the details can be found here:

    http://yuiblog.com/blog/2007/06/12/module-pattern/

    It is really straightforward, and easy for other developers to comprehend. For a simple example:

    var MYLIB = function() {  
        var aPrivateProperty = true;
        var aPrivateMethod = function() {
            // some code here...
        };
        return {
            aPublicMethod : function() {
                aPrivateMethod(); // okay
                // some code here...
            },
            aPublicProperty : true
        };  
    }();
    
    MYLIB.aPrivateMethod() // not okay
    MYLIB.aPublicMethod() // okay
    
    0 讨论(0)
  • 2020-11-22 09:03

    ES2021 / ES12 - Private Methods

    Private method names start with a hash # prefix and can be accessed only inside the class where it is defined.

    class Restaurant {
    
      // private method
      #private_stuff() {
        console.log("private stuff");
      }
    
      // public method
      buy_food() {
        this.#private_stuff();
      }
    
    };
    
    const restaurant = new Restaurant();
    restaurant.buy_food(); // "private stuff";
    restaurant.private_stuff(); // Uncaught TypeError: restaurant.private_stuff is not a function
    

    This is an experimental proposal. ECMAScript 2021 version is expected to be released in June 2021.

    0 讨论(0)
  • 2020-11-22 09:03

    I have created a new tool to allow you to have true private methods on the prototype https://github.com/TremayneChrist/ProtectJS

    Example:

    var MyObject = (function () {
    
      // Create the object
      function MyObject() {}
    
      // Add methods to the prototype
      MyObject.prototype = {
    
        // This is our public method
        public: function () {
          console.log('PUBLIC method has been called');
        },
    
        // This is our private method, using (_)
        _private: function () {
          console.log('PRIVATE method has been called');
        }
      }
    
      return protect(MyObject);
    
    })();
    
    // Create an instance of the object
    var mo = new MyObject();
    
    // Call its methods
    mo.public(); // Pass
    mo._private(); // Fail
    
    0 讨论(0)
  • 2020-11-22 09:05

    Using self invoking function and call

    JavaScript uses prototypes and does't have classes (or methods for that matter) like Object Oriented languages. A JavaScript developer need to think in JavaScript.

    Wikipedia quote:

    Unlike many object-oriented languages, there is no distinction between a function definition and a method definition. Rather, the distinction occurs during function calling; when a function is called as a method of an object, the function's local this keyword is bound to that object for that invocation.

    Solution using a self invoking function and the call function to call the private "method" :

    var MyObject = (function () {
    
        // Constructor
        function MyObject (foo) {
            this._foo = foo;
        }
    
        function privateFun (prefix) {
            return prefix + this._foo;
        }
    
        MyObject.prototype.publicFun = function () {
            return privateFun.call(this, '>>');
        }
    
        return MyObject;
    })();
    
    
    var myObject = new MyObject('bar');
    myObject.publicFun();      // Returns '>>bar'
    myObject.privateFun('>>'); // ReferenceError: private is not defined
    

    The call function allows us to call the private function with the appropriate context (this).


    Simpler with Node.js

    If you are using node.js, you don't need the IIFE because you can take advantage of the module loading system:

    function MyObject (foo) {
        this._foo = foo;
    }
    
    function privateFun (prefix) {
        return prefix + this._foo;
    }
    
    MyObject.prototype.publicFun = function () {
        return privateFun.call(this, '>>');
    }
    
    exports.MyObject = MyObject;
    

    Load the file:

    var MyObject = require('./MyObject').MyObject;
    
    var myObject = new MyObject('bar');
    myObject.publicFun();      // Returns '>>bar'
    myObject.privateFun('>>'); // ReferenceError: private is not defined
    


    (experimental) ES7 with the Bind Operator

    The bind operator :: is an ECMAScript proposal and is implemented in Babel (stage 0).

    export default class MyObject {
      constructor (foo) {
        this._foo = foo;
      }
    
      publicFun () {
        return this::privateFun('>>');
      }
    }
    
    function privateFun (prefix) {
      return prefix + this._foo;
    }
    

    Load the file:

    import MyObject from './MyObject';
    
    let myObject = new MyObject('bar');
    myObject.publicFun();      // Returns '>>bar'
    myObject.privateFun('>>'); // TypeError: myObject.privateFun is not a function
    
    0 讨论(0)
  • 2020-11-22 09:05
    Class({  
        Namespace:ABC,  
        Name:"ClassL2",  
        Bases:[ABC.ClassTop],  
        Private:{  
            m_var:2  
        },  
        Protected:{  
            proval:2,  
            fight:Property(function(){  
                this.m_var--;  
                console.log("ClassL2::fight (m_var)" +this.m_var);  
            },[Property.Type.Virtual])  
        },  
        Public:{  
            Fight:function(){  
                console.log("ClassL2::Fight (m_var)"+this.m_var);  
                this.fight();  
            }  
        }  
    });  
    

    https://github.com/nooning/JSClass

    0 讨论(0)
  • 2020-11-22 09:05

    You have to put a closure around your actual constructor-function, where you can define your private methods. To change data of the instances through these private methods, you have to give them "this" with them, either as an function argument or by calling this function with .apply(this) :

    var Restaurant = (function(){
        var private_buy_food = function(that){
            that.data.soldFood = true;
        }
        var private_take_a_shit = function(){
            this.data.isdirty = true;   
        }
        // New Closure
        function restaurant()
        {
            this.data = {
                isdirty : false,
                soldFood: false,
            };
        }
    
        restaurant.prototype.buy_food = function()
        {
           private_buy_food(this);
        }
        restaurant.prototype.use_restroom = function()
        {
           private_take_a_shit.call(this);
        }
        return restaurant;
    })()
    
    // TEST:
    
    var McDonalds = new Restaurant();
    McDonalds.buy_food();
    McDonalds.use_restroom();
    console.log(McDonalds);
    console.log(McDonalds.__proto__);
    
    0 讨论(0)
提交回复
热议问题