简体   繁体   中英

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?

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.

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

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

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM