I recently came across an intriguing piece of JavaScript code involving prototypes and object instances. This code highlights a common pitfall when working with objects and their prototypes. Let’s take a closer look at what this code does and why it behaves in a particular way.
Code Overview
Here is the code snippet:
function EmployeeNames() {}
EmployeeNames.prototype = {
names: [],
showNames: function() {
return this.names;
}
};
var e1 = new EmployeeNames();
e1.names.push("foo");
console.log(e1.showNames()); // --> foo
var e2 = new EmployeeNames();
e2.names.push("bar");
console.log(e2.showNames()); // --> foo, barExplanation of the Code
- Function Constructor:
function EmployeeNames() {}defines a constructor function for creatingEmployeeNamesobjects.
- Prototype Assignment:
- The
EmployeeNames.prototypeis assigned an object with anamesproperty (an empty array) and ashowNamesmethod that returnsthis.names.
- The
- Creating Instances:
var e1 = new EmployeeNames();creates an instance ofEmployeeNames, ande1.names.push("foo");pushes the string “foo” into thenamesarray.console.log(e1.showNames());logs['foo'].var e2 = new EmployeeNames();creates a second instance,e2, ande2.names.push("bar");pushes the string “bar” into the samenamesarray.console.log(e2.showNames());logs['foo', 'bar'].
Why Does This Happen?
The reason e1 and e2 share the same names array lies in how prototypes work in JavaScript. When EmployeeNames.prototype is defined with a names array, this array is shared across all instances of EmployeeNames created using the new keyword. This means any modification to names by one instance affects all instances, as they all reference the same array in the prototype.
Breakdown of Log Results
- First
console.log(e1.showNames()):- The
namesarray initially contains['foo']aftere1pushes “foo”.
- The
- Second
console.log(e2.showNames()):- When
e2pushes “bar”, it modifies the sharednamesarray, resulting in['foo', 'bar']being logged for bothe1ande2.
- When
Solution to Avoid Shared State
To avoid this issue, it’s better to initialize properties like names inside the constructor function itself:
function EmployeeNames() {
this.names = [];
}
EmployeeNames.prototype.showNames = function() {
return this.names;
};With this change, each instance of EmployeeNames will have its own names array, ensuring that modifications to e1.names do not affect e2.names and vice versa.




