Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JavaScript Classes and Variable Scope

I'm relatively new to JS and I'm having issues properly emulating OOP principles.

I guess I have two questions. Question the first is regarding the many ways to declare variables.

Say I have a class:

function clazz(a)
{
    this.b = 2;
    var c = 3;
    this.prototype.d = 4; // or clazz.prototype.d = 4?
}

var myClazz = new clazz(1); 

Am I correct in the following assessments:

a is a private variable that is instance specific (i.e. different instances of clazz will have unique and independent variables 'a'). It can be accessed from within clazz as: 'a'.

b is a public variable that is instance specific. It can be accessed from within clazz as 'this.b' and from outside clazz as 'myClazz.b'.

c is a private variable that is static, or class specific (i.e. different instances of clazz will share the same 'c' variable). It can be accessed from within any instance of clazz as 'c' and changes in instance of clazz are reflected in all instances of clazz.

d is a public variable that is static/class specific. It can be accessed from anywhere via 'clazz.prototype.d' or 'myClazz.prototype.d'.

The overall issue I have with my understanding of the variable scheme is that there's no way to declare a private variable that is NOT static (i.e. a unique version for every instance of the class).

The second question is with respect to different types of class declarations.

I've been using:

var MySingleton = new function() {...};

to create singletons. Is this correct? I'm also unsure as to the effect of the "new" keyword in this situation as well as appending () function braces to the end of the declaration as so:

var MySingleton = new function() {...}();

I've been using this pattern to declare a class and then instantiate instances of that class:

function myClass() {...};
var classA = new myClass();
var classB = new myClass();

Is this the proper method?

like image 244
Cmc Avatar asked Nov 30 '09 22:11

Cmc


People also ask

Can JavaScript classes have variables?

We can also define private variables in a class. Private variables must be explicitly declared inside the class body and are prefixed by a #. They can only be accessed inside class member functions.

What are the three types of scopes in JavaScript?

JavaScript has 3 types of scope: Block scope. Function scope. Global scope.

What are the two types of scopes in JavaScript?

JavaScript has the following kinds of scopes: Global scope: The default scope for all code running in script mode. Module scope: The scope for code running in module mode.


1 Answers

You are right for a and b:

a is an argument, available only within the scope of the constructor function.

bis a public instance variable, available on all instances created with that constructor function.

c is a private variable, accessible only within the constructor function.

The d declaration is invalid, because the prototype object is meant to be used only on constructor functions, like Clazz.prototype.d = 3;, if you do it like this, the variable will be shared, but you can assign a value on an specific instance, and the default value will be shadowed (through the prototype chain).

For "private variables" you can use the way you declare c, for example:

function Clazz(){
    var c = 3; // private variable

    this.privilegedMethod = function () {
      alert(c);
    };
}

Privileged methods, are public, but they can access "private" variables declared inside the constructor function.

For creating singletons, the easiest way is maybe to use an object literal, like:

var myInstance = {
  method1: function () {
    // ...
  },
  method2: function () {
    // ...
  }
};

And if you want private members on your singleton instance, you can:

var myInstance = (function() {
  var privateVar = '';

  function privateMethod () {
    // ...
  }

  return { // public interface
    publicMethod1: function () {
      // all private members are accesible here
    },
    publicMethod2: function () {
    }
  };
})();

This is has been called the module pattern, it basically allows you to encapsulate private members on an object, by taking advantage of the use of closures.

More info:

  • Private Members in JavaScript
  • Introduction to Object Oriented JavaScript

Edit: About the syntax you post:

var mySingleton = new (function() {
  // ...
})();

By using the new operator, you are declaring and using in one step an "anonymous constructor function", which will generate a new object instance, it is valid but I personally would prefer the "module" pattern approach, to create my own object instance (and avoid new).

Also, reading new function () {}, I think that is not really intuitive and may create confusion, if you don't understand well how the new operator works.

About the parentheses, they are optional, the new operator will call the function constructor without parameters if you don't add them (see ECMA-262, 11.2.2).

like image 112
Christian C. Salvadó Avatar answered Oct 06 '22 08:10

Christian C. Salvadó