使用原型继承创建 Child Class 的方法时出现“.. 不是函数”错误

".. is not a function" Error when creating a method of Child Class using prototype inheritance

我正在学习 JavaScript 原型制作。这里的 Employee 是父级,我在我的 Programmer 原型中继承了它,但是当我尝试 运行 我的子原型(即 Programmer)的 favoriteLanguage 方法时,它表明 favoriteLanguage 不是一个函数。我尝试阅读 Mozilla 文档,但我无法理解这些内容是否相关!谁能用简单的术语帮助我!

编辑:我知道我可以使用 class,但我想了解为什么它在这种情况下不起作用!

代码如下:

function Employee(givenName, givenExperience, givenDivision){
    this.name = givenName;
    this.experience = givenExperience;
    this.division = givenDivision;
}

Employee.prototype.slogan=function(){
    return `I am ${this.name} and this company is the best`;
}

Employee.prototype.joiningYear=function(){
    return 2020 - this.experience;
}

function Programmer(givenName, givenExperience, givenDivision, language, github){
    Employee.call(this,givenName, givenExperience, givenDivision);
    this.language = language;
    this.github = github;
}

Programmer.prototype.favoriteLanguage = function(){   //Error part
    if (this.language == 'python'){
        return 'Python';
    }
    else{
        return 'JavaScript';
    }
}

Programmer.prototype = Object.create(Employee.prototype);
Programmer.prototype.constructor = Programmer;

//Object.setPrototypeOf(Programmer.prototype, Employee.prototype);

let arju = new Programmer("Arju Aman",0,"Developer","javaScript","arjuaman");

console.log(arju);
// console.log(arju.joiningYear());
// console.log(arju.slogan());

console.log(arju.favoriteLanguage());   //called here

问题是您要将 属性 添加到默认的 Programmer.prototype 对象:

Programmer.prototype.favoriteLanguage = function(){
    // ...
}

...但片刻之后,您将用新对象完全替换该对象:

Programmer.prototype = Object.create(Employee.prototype);

新对象不会有您添加到旧对象的 属性。

要修复它,只需将 Programmer.prototype = 语句移动到添加 属性 的语句上方:

function Employee(givenName, givenExperience, givenDivision){
    this.name = givenName;
    this.experience = givenExperience;
    this.division = givenDivision;
}

Employee.prototype.slogan=function(){
    return `I am ${this.name} and this company is the best`;
}

Employee.prototype.joiningYear=function(){
    return 2020 - this.experience;
}

function Programmer(givenName, givenExperience, givenDivision, language, github){
    Employee.call(this,givenName, givenExperience, givenDivision);
    this.language = language;
    this.github = github;
}

// *** Moved
Programmer.prototype = Object.create(Employee.prototype);
Programmer.prototype.constructor = Programmer;

Programmer.prototype.favoriteLanguage = function(){
    if (this.language == 'python'){
        return 'Python';
    }
    else{
        return 'JavaScript';
    }
}

let arju = new Programmer("Arju Aman",0,"Developer","javaScript","arjuaman");

console.log(arju);

console.log(arju.favoriteLanguage());

但是,你提到你正在学习JavaScript。自 2015 年以来,JavaScript 有一种更简单的方法来定义构造函数及其分配给新实例的原型:class 语法:

class Employee {
    constructor(givenName, givenExperience, givenDivision) {
        this.name = givenName;
        this.experience = givenExperience;
        this.division = givenDivision;
    }

    slogan() {
        return `I am ${this.name} and this company is the best`;
    }

    joiningYear() {
        return 2020 - this.experience;
    }
}

class Programmer extends Employee {
    constructor(givenName, givenExperience, givenDivision, language, github) {
        super(givenName, givenExperience, givenDivision);
        this.language = language;
        this.github = github;
    }

    favoriteLanguage() {
        if (this.language == "python"){
            return "Python";
        } else{
            return "JavaScript";
        }
    }
}

let arju = new Programmer("Arju Aman", 0, "Developer", "javaScript", "arjuaman");

console.log(arju);

console.log(arju.favoriteLanguage());

新语法仍然做了很多相同的事情(这仍然是原型继承,它仍然创建了一个构造函数,其中包含 prototype 属性 定义了 new X 将要使用的对象分配新对象等),但使用起来要简单得多,尤其是在继承时。现在也支持私有字段和方法;以下三项提案均已登陆规范:

在没有这些的情况下拥有真正的私人信息是可能的,但要麻烦得多。