1

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. Ordinary vars and parameters of the constructor becomes the private members."

function Container(param) {
    this.member = param;
    var secret = 3;
    var that = this;
}

And for public methods, "this technique is usually used to initialize public instance variables. The constructor's this variable is used to add members to the object."

function Container(param) {
    this.member = param;
}

As you can see both functions have a params paramater and a this.member = param;. Yet one is a private instance variable and the other is a public instance variable?

Tony54
  • 265
  • 1
  • 4
  • 9
  • in both cases, `this.member` is public – Jaromanda X Aug 05 '15 at 12:40
  • 3
    `var secret` is the only private variable. But you can't really call it a private `instance variable` because it's only available inside the constructor. This is JS - throw away everything you know about classical inheritance in every other programming language and learn prototypal inheritance and what you can and cannot do with it. Firstly: there are **NO** purely private instance variables in JS. – Adam Jenkins Aug 05 '15 at 12:40
  • the tutorial states `This constructor makes three private instance variables: param, secret, and that.` ... – Jaromanda X Aug 05 '15 at 12:42
  • There is no "private" in javascript. –  Aug 05 '15 at 12:42
  • @JaromandaX - while I am not one to argue with Crockford, they are not truly `instance` variables in the strictest manner of speaking. If you use the `prototype` of a method, to extend it's functionality, you will not be able to access those `private instance variables` you created in the constructor in any of those methods in a methods prototype, which means they are not really `instance` variables. – Adam Jenkins Aug 05 '15 at 12:44
  • @Adam - Mr Crockford basically states what you just said further on in the tutorial, I wasn't going to reproduce the whole tutorial that the OP was following anyway - as for arguing with Mr Crockford ... I think he's lost it in his old age :p – Jaromanda X Aug 05 '15 at 12:46

2 Answers2

0

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.

Domino
  • 6,314
  • 1
  • 32
  • 58
-1

No one of this variable is trully private because if you instanciate Container you can access to secret variable :

function Container(param) {
    this.member = param;
    var secret = 3;
    var that = this;
}

var container = new Container();
console.log(container.secret);
container.secret = "toto";
console.log(container.secret);
console.log(container);

Here the result :

Console

As you can see you can access to secret without any "Getter/Setter".

If you want to do object javascript with truly private variable, look at this tutorial :

http://blog.stchur.com/2011/09/26/true-private-variables-in-javascript-with-prototype/

OrcusZ
  • 3,555
  • 2
  • 31
  • 48