Javascript property defined on prototype

Viewed 69

I have a very simple JS code as below;

var Worker = function (name) {
    this.name = name;
}
Worker.prototype.jobs = 0;
Worker.prototype.Work = function () {
    console.log("jobs finished", this.name, ++this.jobs);
}
var ca = new Worker("ca");
var cb = new Worker("cb");
ca.Work();// shows 1
cb.Work();// shows 1 (Q: Why is this not printed 2 ?)

Now the above prints 1 for this.jobs twice. I was expecting that since the property "jobs" is defined on the prototype, it would be a shared one (and not really a different copy for each instance). However that does not seem to be the case. Where is my understanding wrong and what am I missing ?

4 Answers

By adding it to the prototype you've made it available as an instance method/property. For it to function how you would like, you need to add it directly to Work:

Worker.jobs = 0;
Worker.Work = function () {
    ++this.jobs;
    return this.jobs;
}

then you could even do something like this:

Worker.prototype.work = () => {
    console.log("jobs finished", this.name, Worker.Work());
}

The function you are called is in the prototype object. But the ´this´ it is referring to, is in the child object. Only if the property does not exist, this[propertyname] lookup will progress up the prototype chain.

// ++this.jobs is a short for this.jobs = this.jobs +1;
// if the child object is missing this.jobs property, it is fetched from the prototype object. So this assigns the 'jobs' property to current object, but looks it up from the prototype object.
Worker.prototype.Work = function () {
   console.log("jobs finished", this.name, ++this.jobs);
}

When you are reading the this.jobs property, the lookup first happens on the object instance itself as an own property first and when it is not found the look up happens on the prototype chain.

So since the jobs property is found on the prototype which is initialized to 0, the value is read from the prototype.

When you increment the this.job, this will create a own property after increment operation, which is why we never see the change in the other instance as the jobs becomes an own property of that particular instance:

var Worker = function (name) {
    this.name = name;
}
Worker.prototype.jobs = 0;
Worker.prototype.Work = function () {
    console.log("jobs is an own property =>", this.hasOwnProperty("jobs"));
    ++this.jobs
    console.log("jobs is now an own property =>", this.hasOwnProperty("jobs"));
    console.log("jobs finished", this.name, this.jobs);
}
var ca = new Worker("ca");
var cb = new Worker("cb");
ca.Work();// shows 1
cb.Work();// shows 1

On the other hand if you directly mutate the property on the prototype, you can see that the change is reflected on the second instance as well:

var Worker = function (name) {
    this.name = name;
}
Worker.prototype.jobs = 0;
Worker.prototype.Work = function () {
    ++Object.getPrototypeOf(this).jobs
    console.log("jobs finished", this.name, this.jobs);
}
var ca = new Worker("ca");
var cb = new Worker("cb");
ca.Work();// shows 1
cb.Work();// shows 2

The use of 'this' is refer to context (closure). For access the shared property you should use 'prototype' instead, to work as expected:

var Worker = function (name) {
    this.name = name;
}
Worker.prototype.jobs = 0;
Worker.prototype.Work = function () {
    console.log("jobs finished", this.name, ++Worker.prototype.jobs);
}
var ca = new Worker("ca");
var cb = new Worker("cb");
ca.Work();// shows 1
cb.Work();// shows 1 (Q: Why is this not printed 2 ?)
Related