【问题标题】:JavaScript inheritance not working as I expectedJavaScript 继承没有像我预期的那样工作
【发布时间】:2017-04-30 13:15:45
【问题描述】:

pe.getName() 有效而 pe.getSalary() 无效的详细信息是什么?

var Employee = function(name) {
  this.name = name;
}

Employee.prototype.getName = function() {
  return this.name;
}

var PermanentEmployee = function(annualSalary) {
  this.annualSalary = annualSalary;
}

PermanentEmployee.prototype.getSalary = function() {
  return this.annualSalary;
}

var employee = new Employee("Mark");

PermanentEmployee.prototype = employee;

var pe = new PermanentEmployee(5000);

document.write(pe.getName());
document.write(pe.getSalary());

【问题讨论】:

    标签: javascript inheritance prototype


    【解决方案1】:

    稍后在您的代码中执行此操作

    PermanentEmployee.prototype = employee;
    

    你可以覆盖这个

    PermanentEmployee.prototype.getSalary = function()
    

    试试这个:

    function Employee(name) {
      this.name = name;
    }
    
    Employee.prototype.getName = function() {
      return this.name;
    }
       
    function PermanentEmployee(name, annualSalary) {
      Employee.call(this, name);  // calling parent's "constructor"
      this.annualSalary = annualSalary;
    }
    PermanentEmployee.prototype = Object.create(Employee.prototype); // setting "inheritance"
    PermanentEmployee.prototype.getSalary = function() {
      return this.annualSalary;
    }
    var pe = new PermanentEmployee("Mark", 5000);
    
    console.log(pe.getName());
    console.log(pe.getSalary());

    【讨论】:

    • 但是我的代码幕后实际发生了什么......请解释一下。
    • 你重置了 _ proto _ ref。 PermanentEmployee 对象到 employee 对象和函数 getSalary() 在变得无法访问之前(在通过 _ proto _ ref. of PermanentEmployee 对象可访问的对象中)。由于getSalary()PermanentEmployee 对象中不再可访问,JS 尝试在原型链中找到它并转到没有此类方法的employee 对象,也没有使用getSalary() 方法引用对象自己通过它的_ proto _ 最终抛出一个错误,因为在任何地方都找不到getSalary() 方法。
    • 这是 Javascript 非常重要的核心部分,您希望从一开始就做好。我已尽力使用上面的解释,这对我的口味非常准确,但对于新手来说可能听起来令人困惑,因此,您应该找到更详细地涵盖该主题的其他材料。这是我的建议。
    • 嗯,谢谢你,先生,它对我有点帮助......我想我必须了解更多关于原型和继承
    • 所以我在构造函数中声明getSalary() 方法会起作用吗?
    【解决方案2】:

    这实际上是预期的行为。如果您想了解原因,我们开始...

    考虑以下架构,可在 Dr.阿克塞尔·劳施迈尔

    在继续之前,这里有一个重要的规则:在 JavaScript 中,当你创建一个“类”的实例时,这个实例将通过它的 引用其构造函数的 prototype 属性 dunder proto__proto__[[Prototype]])。

    左上角

    在您的示例中,EmployeePermanentEmployee 是构造函数。与 JavaScript 中的任何函数一样,它们是 Function 的实例,并且使用 Function.prototype

    var Employee = function(name) {
      this.name = name;
    }
    
    var PermanentEmployee = function(annualSalary) {
      this.annualSalary = annualSalary;
    }
    
    console.log(typeof Object.getPrototypeOf(Employee)); // ES5
    console.log(typeof PermanentEmployee.__proto__); // ES6
    
    console.log(Object.getPrototypeOf(Employee).constructor); // ES5
    console.log(PermanentEmployee.__proto__.constructor); // ES6

    右上角

    当您编写Employee.prototype.getNamePermanentEmployee.prototype.getSalary 时,实际上是在为EmployeePermanentEmployee 的原型属性添加新属性。但是Employee.prototypePermanentEmployee.prototypeObject 的实例并使用Object.prototype

    var Employee = function(name) {
      this.name = name;
    }
    
    Employee.prototype.getName = function() {
      return this.name;
    }
    
    var PermanentEmployee = function(annualSalary) {
      this.annualSalary = annualSalary;
    }
    
    PermanentEmployee.prototype.getSalary = function() {
      return this.annualSalary;
    }
    
    console.log(typeof Employee.prototype);
    console.log(typeof PermanentEmployee.prototype);
    
    console.log(Employee.prototype);
    console.log(PermanentEmployee.prototype);

    由于PermanentEmployee.prototype是一个简单的对象,这样做是不合理的:PermanentEmployee.prototype = employee

    当你这样做时,你会覆盖原型。做一个基本的比较,看看这个带有对象字面量的例子:

    var obj = {
      foo: 'Foo'
    };
    
    obj.bar = 'Bar';
    
    console.log(obj);
    
    obj = 'Baz';
    
    console.log(obj);
    
    obj = {
      foo: 'Foo',
      bar: 'Bar',
      baz: 'Baz'
    };
    
    console.log(obj);

    在使用原型时,您应该牢记这一点...

    右下

    在 JavaScript 中,有几种策略可以创建“纯”对象(函数和数组也是对象……)。你可以:

    • 使用对象字面量:{}
    • 使用构造函数:new Object()
    • 使用Object.create()

    在您的示例中,您使用的是构造函数。因此,您的实例将使用您的构造函数的原型属性,它们本身使用Object 的原型属性。这就是原型链的工作原理!

    var Employee = function(name) {
      this.name = name;
    }
    
    Employee.prototype.getName = function() {
      return this.name;
    }
    
    var PermanentEmployee = function(annualSalary) {
      this.annualSalary = annualSalary;
    }
    
    PermanentEmployee.prototype.getSalary = function() {
      return this.annualSalary;
    }
    
    var employee = new Employee("Mark");
    
    console.log(Object.getPrototypeOf(employee)); // ES5
    console.log(employee.__proto__.constructor); // ES6
    console.log(Object.getPrototypeOf(Object.getPrototypeOf(employee))); // ES5
    console.log(employee.__proto__.__proto__.constructor); // ES6

    当然,如果你在某个地方完全覆盖了你的原型,你就会破坏原型链,它就不会按预期工作......

    【讨论】:

      猜你喜欢
      • 2014-06-28
      • 2014-01-11
      • 2016-06-19
      • 2013-04-11
      • 1970-01-01
      • 2021-02-08
      • 1970-01-01
      • 1970-01-01
      • 2023-01-01
      相关资源
      最近更新 更多