Require and JavaScript memory management.

Memory management is one of those things that can be abstracted away for such a long time that we developers can forget about it. Now whether we should or not, well thats another question. I wanted to talk a little bit about memory management in JavaScript when using require. Now there isnt necessarily any allocation or releasing, however we still need to worry about referencing an object that is still at the same memory location. To demonstrate this I will talk about an issue that I encountered which inspired this post.

The setup

So I was in the process of creating an SDK using require. The way that it is setup is I have the objects defined as their specific module and then they reference an empty JSON object of themselves that is the skeletal structure needed to start manipulating the object. They are defined as such.

		define('Car', ['EmptyCarSkeletalStructure'], function (emptyCar) {
			return function (carName) {//Constructor
				var _data = null;
				function init() {
					_data = emptyCar;
					_data.commonInformation.carName = carName;
				}
				function getCarNamePrivate() {
					return _data.commonInformation.carName;
				}
				init();
				return {'getCarName':getCarNamePrivate};
			}
		});
	

So the way you can see it setup is it is using the define function from require and then calling its module car, referencing an empty car module that will return json for it to then use as the skeletal structure for the class. The actual Car module though returns a function that takes in a car name if desired with its so called constructore. So a way that you would initialize this "class" (it isnt a class but this design makes it like one) is using new Car(); That would then create this "class". So you can then see that call to init at the end of the function so when new Car() is called it will initialize itself to do what is needed when created. So then we added a function which is a private function called getCarNamePrivate. This function can not be directly called however we expose it using the return statement which returns a JSON object with getCarName and then the function as the value. So, so far if someone were to call the following

		var car = new Car("hazil");
		console.log(car.getCarName());
	

They would effectively see the name of the car printed into the console, which in this case his hazil. So that is what our "class" looks like internally and how we would interact with it. The next step to look into is actually manipulating the _data variable which we saw get set to emptyCar in the init method. So lets change it too look like this now.

		define('Car', ['EmptyCarSkeletalStructure'], function (emptyCar) {
			return function (carName) {//Constructor
				var _data = null;
				function init() {
					_data = emptyCar;
					if (carName) {
						_data.commonInformation.carName = carName;
					}
				}
				function getCarNamePrivate() {
					return _data.commonInformation.carName;
				}
				function sName(newName) {
					_data.commonInformation.carName = newName;
				}
				init();
				return {'getCarName':getCarNamePrivate,
						'setCarName':sName};
			}
		});
	

So you can see we created a new method for setting the car's name to something else and called it sName internally while making it look to the outside world like setCarName. So now if you were to make a call to car.setCarName("something"); the name would be update. Another thing is the init function no longer bothers setting the cars name to something if there was no car name passed in.

This is where the magic happens, or rather the un magic? We are going to make the car reset itself to a brand new car as if the car had never been altered. So we will make the following calls.

		var car = new Car("Hazil");
		car.setCarName("something else");
		//Here I decided I dont want this car anymore
		car = null;
		//Then I get a new car
		car = new Car();
		console.log(car.getCarName());//I log the name that is non existent for some crazy reason.
	

So I simply made a car named it to something else and then set car to null effectively throwing away the car and then called new Car() to get a completely new car initialized and everything. Well this is where the trickery happens, if you look at your console you will see that the name "something else" was logged, but we just created a new car right? This is where JavaScript and memory management can get pretty tricky when using 3rd party plugins.

The trickery explained

So what happened here is that require being fancy as it is decides when you require something that it will actually create a module that can keep getting called to, essentially. So while you may be calling new Car() the init function is setting _data to emptyCar, but it isnt grabbing the JSON again and then handing it to this Car "class" again. That would be inefficient, so it is handing the same pointer in again so when we called car.setCarName("something else") since _data was referenceing directly emptyCar through the assignment _data = emptyCar then _data is simply referencing the same area in memory that emptyCar is so whenever you are changing _data you are also changing emptyCar (the skeletal car structure). As you can tell this is bad new bears. So to solve this problem all you need to do thanks to JavaScript being a great language is use thise to initailize a new object instead.

		_data = JSON.parse(JSON.stringify(emptyCar));
	

This will cause your _data to be new every time because the stringify and parse methods create a new JSON object for you. So with that I will finish and keep this in mind when accessing JSON objects!