【问题标题】:javascript hasOwnProperty prototype and inheritancejavascript hasOwnProperty 原型和继承
【发布时间】:2017-02-05 13:41:06
【问题描述】:

我检查了以下问题: javascript what is property in hasOwnProperty?javascript hasOwnProperty and prototype 但找不到我的问题的答案。这是我的代码: 但有些答案让我感到困惑(不像预期的那样)。

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

最后 2 个警报没有提及这些方法,尽管这些方法已被 hasOwnProperty 检测到。令人费解。谢谢。

【问题讨论】:

  • 什么您的预期,您看到的,以及为什么这不是您的预期。
  • 顺便说一句,在我回答失败后,我还发现您的继承不现实......学生继承了学校?
  • 您为什么期望Student.prototype 拥有自己的studentName 属性?您期望它的价值是多少?
  • 如果我说“不符合预期”是在比较 console.log(Object.getOwnPropertyNames(new Student())); 的答案时// 上面写着 [ studentName, schoolName ] 和 console.log(Student.prototype.hasOwnProperty("studentName"));这对 studentName 来说是假的。有人可以解释这两种方法的行为,一种在对象上,另一种在原型上。为什么方法 printStudentName 是原型的属性,而 studentName 是对象的属性(或类似的东西)。谢谢。

标签: javascript properties prototypal-inheritance


【解决方案1】:

首先要注意的是,使用new School 设置Student.prototype 是一种反模式。这是一个反模式,你看到很多 很多,但它是一个反模式。 (这也很奇怪:StudentSchool 有“is-a”关系?!通常会有“has-a”关系[不是继承],但没有“is-a”...... ) 我们会回来的。

回答:

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

从来没有在Student.prototype 上设置studentName 属性,因此它没有该属性也就不足为奇了。 Student 函数会在您调用它时在 instance 上设置一个,但Student.prototype 不是由new Student 创建的实例,因此它从来没有设置一个。

继续:

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

您看不到原型方法的原因是因为getOwnPropertyNames 仅显示直接设置在您调用它的对象上的属性名称(新的School 对象和新的Student 对象)。这些方法不是直接设置在这些对象上的,而是设置在这些对象的 prototype 上的。所以他们没有列出来。


反模式:在 ES5 和更早的语法中,使用构造函数设置原型继承的正确方法是通过 Object.create,而不是调用构造函数。此外,在替换函数的 prototype 属性上的对象后,将其 constructor 属性设置回它应该是有用的:

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

当然,在 ES2015(又名“ES6”)及更高版本中,您可以使用 class 表示法(如果需要,可以为旧版浏览器进行转换),它会为您正确处理。

【讨论】:

  • 好的,谢谢。你的回答对我来说更清楚一点。关于“反模式”脚本,我应该承认我从网络上的某个来源获取了这个 sn-p,但无论如何,我试图理解我在期待其他东西时错在哪里:我怀疑向原型添加一个方法写 this.mymethod 很相似:function()...
  • @allezl'OM:是的,恐怕你到处都看到了,这就是我想把它说出来的原因,所以你会知道该怎么做。 :-)
【解决方案2】:

也许混淆的一部分是 hasOwnProperty 不能像你想象的构造函数那样工作。 但是可以按您对实例的期望工作:

a = new Student()
a.hasOwnProperty("studentName") //true 

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-01-07
    • 2013-07-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-16
    • 2010-09-28
    相关资源
    最近更新 更多