asdfasdf
asdfasdf

Reputation: 804

undefined result using prototype [javascript]

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?

Upvotes: 5

Views: 109

Answers (4)

Ultimater
Ultimater

Reputation: 4738

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);

Upvotes: 1

Mark Schultheiss
Mark Schultheiss

Reputation: 34168

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());

Upvotes: 1

br3nt
br3nt

Reputation: 9586

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

Upvotes: 1

Sami Kuhmonen
Sami Kuhmonen

Reputation: 31153

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.

Upvotes: 2

Related Questions