5

So I'm learning prototype using javascript, and tried some code :

function Employee(name) { this.name= name; }
var m = new Employee("Bob");
var working= { isWorking: true };
Employee.prototype = working; 
alert(m.isWorking);

Unfortunately, I get an undefined message, instead of the true value. Is there a reason to this result?

I have made several tests. I've concluded that reassigning the prototype object causes any previously created instances of the Employee class to be unable to access any properties found inside the newly assigned prototype. Is this accurate?

3
  • 3
    When you create an instance it takes a reference to the constructor's prototype at the time. If you replace the prototype later, existing instances won't reflect that. Once you've created an instance, it's generally expected that you'll extend the prototype rather than replacing it. Commented Dec 8, 2015 at 5:04
  • 5
    The instance's reference to the prototype object is set at construction time (i.e. the line with new). Changing the entire Foo.prototype property object will not change this reference on the instance after. However, changes to the Foo.prototype object will be seen (because it's the same object), so e.g. if you instead did Employee.prototype.isWorking = true;, you would see what you expect Commented Dec 8, 2015 at 5:04
  • For further reading, this is a really good run down of prototypal inheritance: markdalgleish.com/2012/10/… Commented Dec 8, 2015 at 5:24

4 Answers 4

2

Changing the prototype will not affect an already created object. It will only affect the objects created based on that object.

There is a property __proto__ which could be used to change the prototype, but its implementation is not required. ES6 does define setPrototypeOf method to change the prototype, but since it's only in ES6 the support may vary.

Sign up to request clarification or add additional context in comments.

Comments

1

First off, you have created an instance of Employee before you set the prototype, so that object will not have inherited the new prototype values.

Next, any objects created after you have set the prototype will inherit the new prototype object.

Lastly, the object will have the isWorking property, rather than a working property.

So to redo your example:

function Employee(name) { this.name= name; };

var m1 = new Employee("Bob");

var working= { isWorking: true };
Employee.prototype = working; 

var m2 = new Employee("Sam");

alert(m1.isWorking); // undefined
alert(m2.isWorking); // true

Comments

1

Simple fix is to properly assign it.

function Employee(name) {
  this.name = name;
}
var m = new Employee("Bob");
var working = {
  isWorking: true
};
Employee.prototype.working = working;
alert(m.working.isWorking);

A better fix for MULTIPLE employees is to make a class, then create instances of that: play around with it here: http://jsfiddle.net/MarkSchultheiss/p6jyqbgv/1/

"use strict";
function makeClassStrict() {
  var isInternal, instance;
  var constructor = function(args) {
    if (this instanceof constructor) {
      if (typeof this.init == "function") {
        this.init.apply(this, isInternal ? args : arguments);
      }
    } else {
      isInternal = true;
      instance = new constructor(arguments);
      isInternal = false;
      return instance;
    }
  };
  return constructor;
}
var EmployeeClass = makeClassStrict();
EmployeeClass.prototype.init = function(employeeName, isWorking) {
  var defaultName = 'notbob';
  this.name = employeeName ? employeeName : defaultName;
  this.working = !!isWorking;
};
// call this to get the name property
EmployeeClass.prototype.getName = function() {
  return this.name
};
//note no "new" needed due to the makeClassStrict that does that
var m = EmployeeClass("Bob");
alert(m.working +":"+ m.name);
m.working = true;
alert(m.working +":"+ m.name);
var notbob =  EmployeeClass("Charlie",false);
alert(notbob.working +":"+ notbob.name);
alert(notbob.getName()+ m.getName());

Comments

1

You cannot override the entire prototype property and expect already existing instances to work. JavaScript doesn't work that way. But you can loop through the prototype object and unset anything already set, then loop through your new object, and set it to something else.

function Employee(name) { this.name= name; }
var m = new Employee("Bob");
var working= { isWorking: true };
for(var j in Employee.prototype){delete Employee.prototype[j];}//unset all properties, the same as setting to {}
for(j in working){Employee.prototype[j]=working[j];}//set the properties
alert(m.isWorking);

1 Comment

You can't really do this, as any explicitly declared attributes of the prototype obsivously cannot be deleted using the delete keyword.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.