Implementing private instance variables in Javascript

后端 未结 4 991
夕颜
夕颜 2020-12-05 03:07

I don\'t know how I\'ve missed this for so long. I\'ve been presuming private instance variables to work like this, but they don\'t. They\'re private (as in non-global), cer

相关标签:
4条回答
  • 2020-12-05 03:32

    Privates are expensive, avoid them if possible

    Private doesn't exist. You can do one of two things to emulate this.

    • closures
    • Weakmaps

    Closures

    function makePrinter(word) {
      return {
        print: function () {
          console.log(word)
        }
      }
    }
    

    WeakMap

    Browser support for weakmaps is awful. You will probably need an emulation, I recommend pd.Name

    var Printer = (function () {
      var privates = function (obj) {
        var v = map.get(obj)
        if (v === undefined) {
          v = {}
          map.set(obj, v)
        } 
        return v
      }, map = new WeakMap()
    
      return {
        constructor: function (word) {
          privates(this).word = word
        },
        print: function () {
          console.log(privates(this).word)
        }
      }
    }());
    

    Sensible objects

    var Printer = {
      constructor: function (word) {
        this._word = word
      },
      print: function () {
        console.log(this._word)
      }
    }
    
    0 讨论(0)
  • 2020-12-05 03:35

    A slight modification to the code using this will work. The correct instance of Printer.prototype.print was not being instantiated for the a object.

    var Printer = (function(){
        var _word;
    
        Printer = function(word){
            this._word = word;
        }
    
        _print = function(){
            console.log(this._word);
        }
    
        Printer.prototype = {
            print: _print
        }
    
        return Printer;
    })();
    
    var a = new Printer("Alex");
    var b = new Printer("Bob");
    
    a.print(); //Prints Alex
    b.print(); //Prints Bob
    
    0 讨论(0)
  • 2020-12-05 03:38

    If you are willing to use ES2015 classes (I already answered it here, but repeating for the sake of convenience),

    with ESNext, you can use Javascript private variables like this:

    class Foo {
      #bar = '';
      constructor(val){
          this.#bar = val;
      }
      otherFn(){
          console.log(this.#bar);
      }
    }
    

    Private field #bar is not accessible outside Foo class.

    0 讨论(0)
  • 2020-12-05 03:45

    You're doing some wonky stuff with that closure. _word needs to be declared in the Printer function, not lost in anonymous-closure land:

    function Printer(word) {
        var _word = word;
    
        this.print = function () {
            console.log(_word);
        }
    }
    
    var a = new Printer("Alex");
    var b = new Printer("Bob");
    
    a.print(); //Prints Alex
    b.print(); //Prints Bob
    

    This keeps _word private, at the expense of creating a new print function on every Printer instance. To cut this cost, you expose _word and use a single print function on the prototype:

    function Printer(word) {
        this._word = word;
    }
    
    Printer.prototype.print = function () {
        console.log(this._word);
    }
    
    var a = new Printer("Alex");
    var b = new Printer("Bob");
    
    a.print(); //Prints Alex
    b.print(); //Prints Bob
    

    Does it really matter that _word is exposed? Personally, I don't think so, especially given the _ prefix.

    0 讨论(0)
提交回复
热议问题