1

I've checked questions: javascript what is property in hasOwnProperty? and javascript hasOwnProperty and prototype but couldn't find the answer to my problem. Here is my code: But some answers are puzzling me (NOT as expected).

function School(schoolName) {
  this.schoolName = schoolName;
}
School.prototype.printSchoolName = function() {
  console.log(this.schoolName);
}

function Student(studentName, schoolName) {
  this.studentName = studentName;
  this.schoolName = schoolName; // alternative : School.call(this, schoolName);
}
Student.prototype = new School(); // force l'héritage des propriétés de School
Student.prototype.printStudentName = function() {
  console.log(this.studentName);
}
var s = new Student("Victor", "IUT");
s.printStudentName(); // works fine
s.printSchoolName(); // works fine
console.log(Student.prototype.hasOwnProperty("printStudentName")); // works as expected: true
console.log(Student.prototype.hasOwnProperty("printSchoolName")); // works as expected: false
console.log(Student.prototype.hasOwnProperty("studentName")); //  NOT as expected: false
console.log(School.prototype.hasOwnProperty("schoolName")); //  NOT as expected: false
console.log(Object.getOwnPropertyNames(new School())); // schoolName
console.log(Object.getOwnPropertyNames(new Student())); // studentName, schoolName

The last 2 alerts don't mention the methods, though these methods have been detected by hasOwnProperty. Puzzling. Thank you.

Community
  • 1
  • 1
allez l'OM
  • 547
  • 4
  • 13
  • Say **what** you expected, what you see instead, and why that isn't what you expect. – T.J. Crowder Feb 05 '17 at 13:51
  • 1
    BTW after my failed answer I also see that your inheritance isn't realistic... Student inherits School? – Matías Fidemraizer Feb 05 '17 at 13:53
  • 1
    Why did you expect `Student.prototype` to have an own `studentName` property? And what did you expect its value to be? – Bergi Feb 05 '17 at 14:01
  • If I say "Not as expected" is when comparing the answer of console.log(Object.getOwnPropertyNames(new Student())); // which says [ studentName, schoolName ] and console.log(Student.prototype.hasOwnProperty("studentName")); which says false for studentName. Can someone explain the behaviour of the two methods, one on the object, the other on the prototype. Why the method printStudentName is a property of the prototype and studentName a property of the object (or something like that).Thank you. – allez l'OM Feb 06 '17 at 15:14

2 Answers2

3

The first thing to note is that using new School to set up Student.prototype is an anti-pattern. It's an anti-pattern you see a lot, but it's an anti-pattern. (It's also bizarre: Student has an "is-a" relationship with School?! Normally there'd be a "has-a" relationship [not inheritance], but not an "is-a"...) We'll come back to it.

Answering:

console.log(Student.prototype.hasOwnProperty("studentName"));
//  NOT as expected: false

Nothing ever sets a studentName property on Student.prototype, so it's no surprise that it doesn't have the property. The Student function will set one on the instance when you call it, but Student.prototype isn't an instance created by new Student, so it's never had one set on it.

Moving on to:

console.log(School.prototype.hasOwnProperty("schoolName"));
//  NOT as expected: false

Same explanation.

Moving on to:

console.log(Object.getOwnPropertyNames(new School()));
// schoolName
console.log(Object.getOwnPropertyNames(new Student()));
// studentName, schoolName

The reason you don't see the prototype methods there is because getOwnPropertyNames shows only the names of properties directly set on the object you call it on (the new School object and the new Student object). The methods aren't directly set on those, they're set on the prototype of those objects. So they're not listed.


Re the anti-pattern: In ES5 and earlier syntax, the correct way to set up prototypical inheritance with constructor functions is via Object.create, not calling the constructor. Also, after replacing the object on a function's prototype property, it's useful to set its constructor property back to what it should be:

Student.prototype = Object.create(School.prototype);
Student.prototype.constructor = Student;

Of course, in ES2015 (aka "ES6") and later, you can use class notation (transpiling if necessary for older browsers), which handles doing it correctly for you.

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • Ok, thank you. Your answer is a bit clearer for me. Regarding the "antipattern" scripting, I should confess that I took this snippet from some source on the web, but anyway, I was trying to undestand where I was wrong in expecting something else : I suspected that adding a method to the prototype was simlar to write this.mymethod : function()... – allez l'OM Feb 06 '17 at 15:19
  • @allezl'OM: Yeah, I'm afraid you see that all over the place, that's why I wanted to call it out, so you'd know what to do instead. :-) – T.J. Crowder Feb 06 '17 at 15:25
0

maybe part of the confusion is hasOwnProperty doesn't work as you think for constructor function. But works as you'd expect for the instance:

a = new Student()
a.hasOwnProperty("studentName") //true 
Joel Blum
  • 7,750
  • 10
  • 41
  • 60