Understanding public/private instance variables

前端 未结 2 618
耶瑟儿~
耶瑟儿~ 2021-01-25 09:14

I am reading a tutorial on public/private methods and can\'t make sense of the difference.

For a private method it says, \"Private members are made by the constructor. O

2条回答
  •  小鲜肉
    小鲜肉 (楼主)
    2021-01-25 09:44

    Understanding closures

    Opening a new function body creates a new scope. This kind of scope is called a closure in JS. Variables created within that scope are accessible in all its sub-scopes. This means any var-created variable will be made visible to sub-functions. In this example, myTemporaryVar is accessible within subScope.

    function myParentScope() {
      var myTemporaryVar = "sample";
    
      function subScope() {
        console.log(myTemporaryVar);
      }
    
      return subScope();
    }
    

    When you use a function with the new keyword, a new closure is created for the current instance. Any function created within that constructor will keep access to the scope variables. In the next example, the function sayHi can access the temporary variable myName.

    function Person(name) {
      var myName = name;
      this.sayHi = function() {
        console.log("Hi, my name is " + myName + ".");
      };
    }
    
    p = new Person("Bob");
    p.sayHi(); // Hi, my name is Bob.
    

    Actually, passed parameters are the same as var-created variables. The constructor's parameters are accessible within any sub-function. So the previous example can be reduced to:

    function Person(name) {
      this.sayHi = function() {
        console.log("Hi, my name is " + name + ".");
      };
    }
    
    p = new Person("Bob");
    p.sayHi(); // Hi, my name is Bob.
    

    This is a very unique feature of JavaScript because it means var-created variables still exist after the end of the function as long as there still is a way to access them.

    Simulating Class-based OOP privacy

    Closures can be "abused" to create private members with getter and setter functions.

    function Person(name) {
      this.getName = function() {
        return name;
      };
    
      this.setName = function(newname) {
        name = newname;
      };
    }
    
    p = new Person("Bob");
    console.log(p.getName()); // "Bob"
    p.setName("Alice");
    console.log(p.getName()); // "Alice"
    p.name; // undefined
    

    Why this is not true privacy

    The getter and setter have to be created within the constructor in order to access the var-variable. Methods added in the common prototype-extension way can't access them. Prototype-methods have to use the setters and getters too, which makes the privacy of such variables quite useless.

    Person.prototype.sayGoodMorning = function() {
      console.log("Good morning, my name is " + this.getName() + ".");
    }
    

    The only way to directly access the variable within a method is to actually create it in the constructor. But putting all methods inside the constructor is extremely inefficient as a new copy of the methods will be created for each instance. This is why many people prefer simply using custom notation to identify would-be private members. The Google JavaScript Style Guide recommends placing an underscore at the end of the variable name.

    function Person(name) {
      this.name_ = name;
    }
    
    Person.prototype.getName = function() {
      return this.name_;
    }
    
    Person.prototype.setName = function(name) {
      this.name_ = name;
    }
    
    Person.prototype.sayGoodMorning = function() {
      console.log("Good morning, my name is " + this.name_ + ".");
    }
    

    It is the responsibility of the programmer to not be stupid and access the would-be private members. Note that this goes in total contradiction with Crockford's opinion, but to each is own. I learned JS after Python, so the underscore privacy is like a second nature to me.

提交回复
热议问题