JavaScript prototypes for C / C ++ / C # / Java programmers
- Tutorial
JavaScript differs from many other "object-oriented" programming languages in that there are objects in it, but no classes. Instead of classes in JavaScript, there are prototype chains and some other tricks that take time to comprehend. When switching to JavaScript, professional programmers in other languages encounter the problem of quickly entering its object model.
This text is written in order to give a beginner or episodic JavaScript developer an idea of how to create objects in JavaScript, from simple “structural”, as in C, to more “object-oriented”, as in C ++ / C # / Java.
The article can be recommended both to beginners in programming and to backend programmers who write JavaScript only occasionally.
Objects are entities that possess
For ease of introduction to an object, objects can be represented as instances of the corresponding “classes” that exist in memory only after the program starts.
Objects can be generated during the life of the program, change, disappear.
Compare conditional code in C and C ++:
In these examples, we have described the Person object in C and C ++. Not “created an object”, but “described its fields and methods”, so that later you could create such objects and use them.
Also look at the appropriate ways to create one Person object in C and C ++:
These two programs do the same thing: they create an object and allow you to use the functions associated with it
As we can see, even the related languages C and C ++ offer slightly different ways to describe the Person object. In one case, we describe an object through a data structure
Why can people prefer C ++ and the "object-oriented approach", since we can do about the same thing in C, "without classes", and in C ++? There are some good answers that are relevant in the context of learning JavaScript, in which you can use both the C approach and the C ++ approach:
JavaScript programmers also take advantage of object programming, but it lacks “classes” as a syntactic way to describe objects.
We could use the C approach in JavaScript when we describe an object through a data structure and a set of functions that work on data:
Try copying all this code into the program
But this method has the same drawbacks of the C variant as mentioned above. Let's try again, but only this time we will “shove” the methods
Please note that we simply moved the functions from the outside to the
This is pretty redundant. We use the following trick: as in C ++, Java and other languages, JavaScript has a special variable

The resulting function
How to make sure not to create these functions every time anew? How to make the object referenced by the person, fields
To solve just this problem, JavaScript has a mechanism called "prototypes", or rather, "prototype chains". The concept is simple: if an object does not have its own method or field, then the JavaScript engine tries to find this field in the prototype. And if the prototype does not have a field, then they try to find the field with the prototype prototype. Etc. Try to twist the following code in Node.JS by copying it to

We see that if you indicate that the prototype of the object
Therefore, you can do the methods once, put them in the prototype, and
Try this code in
This method of specifying a prototype of an object has two drawbacks. The first is that the special attribute is
Fortunately, another JavaScript trick comes to the rescue, which is standard and compatible with all browsers.
If you call a function not just by name
With this knowledge, it’s easy to understand how the createPerson code written above, using the supernova attribute
Pay attention to the following aspects:
In principle, you can not change the whole object that it points to
Please note that the function body is
turned into a pretty awful sequence of manipulations with
This manual initialization of the attributes of the object (
We can simplify the initialization of an object with many fields using the jQuery.extend function , which simply copies attributes from one object to another:
In addition, we can not pass a bunch of fields to the arguments of the function, but pass an object with the fields we need to the input of the function:
(Unfortunately, because of the need to use
This code already looks simple and compact. But why are we creating a “new createPerson”? It's time to rename the method to a more appropriate name:
Here's what it looks like in the Safari or Chrome console:

This form of writing is already very similar to how a class is written and works in C ++, which is why in JavaScript a function is
This text is written in order to give a beginner or episodic JavaScript developer an idea of how to create objects in JavaScript, from simple “structural”, as in C, to more “object-oriented”, as in C ++ / C # / Java.
The article can be recommended both to beginners in programming and to backend programmers who write JavaScript only occasionally.
Objects and classes in C and C ++
Objects are entities that possess
- identity (identity, the ability to distinguish one object from another),
- state (state, attributes, fields),
- and behavior (behavior, methods, functions that can change state).
For ease of introduction to an object, objects can be represented as instances of the corresponding “classes” that exist in memory only after the program starts.
Objects can be generated during the life of the program, change, disappear.
Compare conditional code in C and C ++:
- C
struct Person { char *firstName; char *lastName; int yearOfBirth; } // Compute person's age in a given year. void computeAge(struct Person *person, int currentYear); // Set a new last name, possibly deallocating the old one. void setLastName(struct Person *person, char *newLastName);
- C ++
class Person { char *firstName; char *lastName; int yearOfBirth; void computeAge(int currentYear); void setLastName(char *newLastName); }
In these examples, we have described the Person object in C and C ++. Not “created an object”, but “described its fields and methods”, so that later you could create such objects and use them.
Also look at the appropriate ways to create one Person object in C and C ++:
- C
struct Person *p = malloc(sizeof(*p)); setLastName(p, "Poupkine"); printf("Person's age is %d\n", computeAge(p, 2013));
- C ++
Person *p = new Person; p->setLastName("Poupkine"); printf("Person's age is %d\n", p->computeAge(2013));
These two programs do the same thing: they create an object and allow you to use the functions associated with it
setLastName
, computeAge
(behavior) to change or poll the state of the object (state). We can access the created object at any time through the p (identity) pointer. If we create another object Person *m = new Person
, we can use the methods of the new object by accessing it through the m pointer. Pointers p and m will point to different objects, each with its own state, albeit with the same set of methods (behavior). As we can see, even the related languages C and C ++ offer slightly different ways to describe the Person object. In one case, we describe an object through a data structure
struct Person
and friendly features somewhere nearby. In the other case, we syntactically put both the data and the functions in the same one class Person
. Why can people prefer C ++ and the "object-oriented approach", since we can do about the same thing in C, "without classes", and in C ++? There are some good answers that are relevant in the context of learning JavaScript, in which you can use both the C approach and the C ++ approach:
- Namespaces In the C variant, we defined the computeAge function. This function is located in the global namespace: it is “visible” to the entire program. In another place, creating such a function now fails. But what if we made a new kind of objects, say, Pony, and we want to make a similar method that calculates the age of a pony? We will not only need to create a new ponyComputeAge () method, but also rename the old method to achieve uniformity: personComputeAge (). In general, we “clutter up” the namespace, making the creation of new types of objects more and more difficult over time. If we put the computeAge () function in a class, as in C ++, we can have many similar functions in different classes. They will not interfere with each other.
- Information hiding. In the C variant, who has a pointer p to the Person structure, he can change any field in the object. For example, you can say p-> yearOfBirth ++. So doing - arbitrarily changing arbitrary fields of arbitrary objects - is considered bad practice. After all, often you need not just to change the field, but to consistently change several fields of the object. And who can do this better and more correctly than a specialized procedure (method)? Therefore, it is worthwhile to be able to prohibit changing fields directly, and letting them be changed only using appropriate methods. In C, this is difficult, so they are rarely used. But in C ++, this is elementary. It is enough to declare some attributes of the private object, and then they can be accessed only from inside the class methods:
class Person { // Эти данные могут менять только функции computeAge и setLastName: private: char *firstName; char *lastName; int yearOfBirth; // Эти функции (методы) доступны всем: public: void computeAge(int currentYear); void setLastName(char *newLastName); }
- Create an interface. In the C version, we are forced to remember for each object how to get age for it. For one object we will call
ponyComputeAge()
for anotherpersonComputeAge()
. In the C ++ version, we can just remember that calculating the age of any object is done throughcomputeAge()
. That is, we introduce a single interface for calculating age, and use it in an application to many objects. It's comfortable.
JavaScript Objects and Prototypes
JavaScript programmers also take advantage of object programming, but it lacks “classes” as a syntactic way to describe objects.
Naive way
We could use the C approach in JavaScript when we describe an object through a data structure and a set of functions that work on data:
function createPerson(first, last, born) {
var person = { firstName: first,
lastName: last,
yearOfBirth: born };
return person;
}
function computeAge(p, currentYear) {
return currentYear - p.yearOfBirth;
}
function setLastName(p, newLastName) {
p.lastName = newLastName;
}
// Create a new person and get their age:
var p = createPerson("Anne", "Hathaway", 1982);
console.log(p);
console.log(computeAge(p, 2013));
Try copying all this code into the program
node
(pre-installing the Node.JS project ) and see what it outputs.Sweeping namespaces
But this method has the same drawbacks of the C variant as mentioned above. Let's try again, but only this time we will “shove” the methods
setLastName()
and the computeAge()
“inside” of the object. This way we “unload” the global namespace, we will not litter it:function createPerson(first, last, born) {
var computeAgeMethod = function(p, currentYear) {
return currentYear - p.yearOfBirth;
}
var setLastNameMethod = function(p, newLastName) {
p.lastName = newLastName;
}
var person = { firstName: first,
lastName: last,
yearOfBirth: born,
computeAge: computeAgeMethod,
setLastName: setLastNameMethod
};
return person;
}
// Create a new person and get their age:
var p = createPerson("Anne", "Hathaway", 1982);
// Note the p.computeAge(p) syntax, instead of just computeAge(p).
console.log(p.computeAge(p, 2013));
console.log(p["computeAge"](p, 2013));
Please note that we simply moved the functions from the outside to the
createPerson
inside. The function body has not changed. That is, each function still expects an argument p
with which it will work. The method of calling these methods has not changed much: yes, instead of calling the global function, you need to call the computeAge
method of the object p.computeAge
, but still the function expects the p
first argument. This is pretty redundant. We use the following trick: as in C ++, Java and other languages, JavaScript has a special variable
this
. If the function is called on its own ( f()
), then this variable points to the global object (in the browser it will be window
). But if a function is called through a point, as a method of some object, (p.f()
), then a pointer to this very object p is passed to it as this. Since we will still be forced to call methods through accessing the corresponding fields of the object ( p.computeAge
), then the methods this
will already exist and set to the correct value p
. Rewrite the code using this knowledge. Also try copying it to node
.function createPerson(first, last, born) {
var computeAgeMethod = function(currentYear) {
return currentYear - this.yearOfBirth;
}
var setLastNameMethod = function(newLastName) {
this.lastName = newLastName;
}
var person = { firstName: first,
lastName: last,
yearOfBirth: born,
computeAge: computeAgeMethod,
setLastName: setLastNameMethod
};
return person;
}
// Create a new person and get their age:
var p = createPerson("Anne", "Hathaway", 1982);
console.log(p.computeAge(2013));

Prototypes
The resulting function
createPerson
has the following drawback: it does not work very fast, and spends a lot of memory every time you create an object. Each time createPerson
JavaScript is called, it constructs two new functions, and assigns them as values to the fields "computeAge" and "setLastName". How to make sure not to create these functions every time anew? How to make the object referenced by the person, fields
computeAge
, and setLastName
it was not, but the methods person.computeAge()
and person.setLastName()
continued to work?To solve just this problem, JavaScript has a mechanism called "prototypes", or rather, "prototype chains". The concept is simple: if an object does not have its own method or field, then the JavaScript engine tries to find this field in the prototype. And if the prototype does not have a field, then they try to find the field with the prototype prototype. Etc. Try to twist the following code in Node.JS by copying it to
node
:var obj1 = { "a": "aVar" };
var obj2 = { "b": "bVar" };
obj1
obj2
obj2.a
obj2.b
obj2.__proto__ = obj1;
obj1
obj2
obj2.a
obj2.b

We see that if you indicate that the prototype of the object
obj2
is an object obj1
, then the obj2
properties of the object “appear” obj1
, such as the field “a” with the value “aVar”. However, printing obj2
does not show the presence of the attribute “a” in the object. Therefore, you can do the methods once, put them in the prototype, and
createPerson
convert them to take advantage of this prototype:function createPerson(first, last, born) {
var person = { firstName: first,
lastName: last,
yearOfBirth: born };
person.__proto__ = personPrototype;
return person;
}
var personPrototype = {
"computeAge": function(currentYear) {
return currentYear - this.yearOfBirth;
}, // обратите внимание на запятую
"setLastName": function(newLastName) {
this.lastName = newLastName;
}
}
// Create a new person and get their age:
var p = createPerson("Anne", "Hathaway", 1982);
console.log(p);
console.log(p.computeAge(2013));
Try this code in
node
. Notice which simple object, without its own methods, is shown through console.log(p)
. And that the method still works for this simple object computeAge
. This method of specifying a prototype of an object has two drawbacks. The first is that the special attribute is
__proto__
very new, and may not be supported by browsers. The second drawback is that even after stopping cluttering up the namespace with functions computeAge
, setLastName
we still dirtied it with a name personPrototype
. Fortunately, another JavaScript trick comes to the rescue, which is standard and compatible with all browsers.
If you call a function not just by name
f()
, but through new f()
(compare with C ++ or Java!), Then two things happen:- A new empty object {} is created, and this in the body of the function begins to point to it.
More details. By default, when calling a functionf()
, an inside accessible functionthis
simply points to the global context; that is, to where it shows in the browserwindow
, orglobal
at Node.JS.var f = function() { console.log(this); }; f() // Выведет в браузере то же, что и строка ниже: console.log(window)
We know that if you call a function as a field of any objectp.f()
, then this of this function will point p to this object already. But if you call the function throughnew f()
, a fresh empty object will be created{}
, andthis
inside the function it will already point to it. Try in node:var f = function() { }; console.log({ "a": "this is an object", "f": f }.f()); console.log(new f());
- In addition, each function has a special attribute
.prototype
. The object that the attribute points to.prototype
will automatically become the prototype of the newly created object from point 1.
Try it innode
:var fooProto = { "foo": "prototype!" }; var f = function() { }; (new f()).foo // Выведет undefined f.prototype = fooProto; (new f()).foo // Выведет "prototype!"
With this knowledge, it’s easy to understand how the createPerson code written above, using the supernova attribute
__proto__
, is equivalent to this more traditional code:function createPerson(first, last, born) {
this.firstName = first;
this.lastName = last;
this.yearOfBirth = born;
}
createPerson.prototype = {
"computeAge": function(currentYear) {
return currentYear - this.yearOfBirth;
}, // обратите внимание на запятую
"setLastName": function(newLastName) {
this.lastName = newLastName;
}
}
// Create a new person and get their age:
var p = new createPerson("Anne", "Hathaway", 1982);
console.log(p);
console.log(p.computeAge(2013));
Pay attention to the following aspects:
- we call new createPerson instead of createPerson;
- we set the prototype object once from outside the function, so as not to construct functions every time we call createPerson;
In principle, you can not change the whole object that it points to
createPerson.prototype
, but simply separately set the necessary fields for it. This idiom can also be found in industrial JavaScript code:createPerson.prototype.computeAge = function(currentYear) {
return currentYear - this.yearOfBirth;
}
createPerson.prototype.setLastName = function(newLastName) {
this.lastName = newLastName;
}
Connecting a jQuery library slice
Please note that the function body is
createPerson
instead of simple and clearfunction createPerson(first, last, born) {
var person = { firstName: first,
lastName: last,
yearOfBirth: born };
return person;
}
turned into a pretty awful sequence of manipulations with
this
:function createPerson(first, last, born) {
this.firstName = first;
this.lastName = last;
this.yearOfBirth = born;
}
This manual initialization of the attributes of the object (
firstName
, lastName
) into the values of the arguments ( first
, last
) is suitable for variants with a very small number of arguments. But for large and branchy configurations, manual enumeration of attributes becomes inconvenient and too verbose. We can simplify the initialization of an object with many fields using the jQuery.extend function , which simply copies attributes from one object to another:
function createPerson(first, last, born) {
var person = { firstName: first,
lastName: last,
yearOfBirth: born });
$.extend(this, person);
}
In addition, we can not pass a bunch of fields to the arguments of the function, but pass an object with the fields we need to the input of the function:
function createPerson(person) {
$.extend(this, person);
}
var p = new createPerson({ firstName: "Anne",
lastName: "Hathaway",
yearOfBirth: 1982 });
console.log(p);
(Unfortunately, because of the need to use
jQuery
, this code is easiest to try already in the browser, and not in terminal C. node
) This code already looks simple and compact. But why are we creating a “new createPerson”? It's time to rename the method to a more appropriate name:
function Person(person) {
$.extend(this, person);
}
Person.prototype.computeAge = function(currentYear) {
return currentYear - this.yearOfBirth;
}
Person.prototype.setLastName = function(newLastName) {
this.lastName = newLastName;
}
var anne = new Person({ firstName: "Anne",
lastName: "Wojcicki",
yearOfBirth: 1973 });
var sergey = new Person({ firstName: "Sergey",
lastName: "Brin",
yearOfBirth: 1973 });
console.log(anne);
console.log(sergey);
Here's what it looks like in the Safari or Chrome console:

This form of writing is already very similar to how a class is written and works in C ++, which is why in JavaScript a function is
Person
sometimes called a class. For example, you could say: "the Person class has a computeAge method."