Tag Archives: prototype

JavaScript

JavaScript: private variable with prototype access

I was programming Java for over 6 years and I still sometimes think in object oriented fashion (you know: classes, static methods, interfaces, etc.). One of my recent problem to solve was to write an object with some private collection and public interface in JavaScript. So my first solution was like this:

var MyArray = function() {
	var array = [];
	this.add = function(item) {
		array.push(item);
	}
	this.getAll = function() {
		return array;
	}
}

var myArray = new MyArray();
myArray.add("some item");
console.log(myArray.getAll()); // ['some item']

That solution is perfectly fine is you need only couple of instances of this object. But memory usage is always my concern, so I wanted to make it better. In Java you don’t have to think about such issues, because you have classes. In JavaScript you have only objects and theirs prototypes. So maybe lets try to move methods add and getAll to prototype?

var MyArray = function() {
	var array = [];
	MyArray.prototype.add = function(item) {
		array.push(item);
	}
	MyArray.prototype.getAll = function() {
		return array;
	}
}

var myArray1 = new MyArray();
myArray1.add("some item 1");
console.log(myArray1.getAll()); // ['some item 1']

var myArray2 = new MyArray();
myArray2.add("some item 2");
console.log(myArray2.getAll()); // ['some item 2']
console.log(myArray1.getAll()); // ['some item 2'] - ERROR

As you see, this approach is wrong. Prototype will not work that way. Array in those methods is a reference to array created in last constructor call.

There are couple of options to solve this issue.

Use Safe Factory Pattern

Basically Safe Factory Pattern uses inner state variable to hold all references to objects used by prototype methods. Great description of this pattern can be found here: http://www.codeproject.com/Articles/133118/Safe-Factory-Pattern-Private-instance-state-in-Jav

There are also ready to use modules implementing this pattern:
https://github.com/dcleao/private-state/ – I didn’t use it, but if you did, please let me know in comments.

Use Safe Factory Pattern with implementation based on WeekMap

var MyArray = (function() {
  var refs = new WeakMap();

  var MyArray = function() {
    refs.set(this, []);
  };

  MyArray.prototype.add = function(val) {
    refs.get(this).push(val);
  };

  MyArray.prototype.getAll = function() {
    console.log(refs.get(this));
  };

  return MyArray;
})();

var myArray1 = new MyArray();
myArray1.add("some item 1");
console.log(myArray1.getAll()); // ['some item 1']

var myArray2 = new MyArray();
myArray2.add("some item 2");
console.log(myArray2.getAll()); // ['some item 2']
console.log(myArray1.getAll()); // ['some item 2'] - FINE!

Add methods as constructor function properties and bind them inside object

var MyArray = function() {
	var array = [];

	this.add = MyArray.add.bind(null, array);
	this.getAll = MyArray.getAll.bind(null, array);
}

MyArray.add = function(array, item) {
	array.push(item);
}
MyArray.getAll = function(array) {
	return array;
}

var myArray1 = new MyArray();
myArray1.add("some item 1");
console.log(myArray1.getAll()); // ['some item 1']
var myArray2 = new MyArray();
myArray2.add("some item 2");
console.log(myArray2.getAll()); // ['some item 2']
console.log(myArray1.getAll()); // ['some item 2'] - FINE!

This approach has small disadvantage, because for each instance of MyArray we need to bind both methods.

When I first encounter this issue I started to think that JavaScript is having problems in places, where you cannot imagine as for example Java developer used to having classes, static methods, etc. Lesson learned is that when working with other technology stack, we have to stop thinking with patterns and drop some habits.

What do you think all solution mentioned above? Which is the best? If you have any other, please let me know.