原型:这两个脚本之间的区别

Prototype: Difference between these two scripts

本文关键字:脚本 两个 之间 区别 原型      更新时间:2023-09-26

考虑在JavaScript中构造对象层次结构的两个版本:

版本 1

function Employee() {
    this.name = "NoName";
    this.dept = "NoDept";
};
function Manager() {
    Employee.call(this);
    this.reports = "Nobody";
}
//Manager.prototype = Object.create(Employee.prototype);
var m = new Manager();
console.log(m.name);

版本 2

function Employee() {
    this.name = "NoName";
    this.dept = "NoDept";
};
function Manager() {
    //Employee.call(this);
    this.reports = "Nobody";
}
Manager.prototype = Object.create(Employee.prototype);
var m = new Manager();
console.log(m.name);

在第一个版本中,即使我们不使用原型继承(当然是因为 call() 方法(,也可以访问 name 属性。在第二个版本中,我们注释掉call()并定义原型链,但name属性无法访问。

这让我想知道,那么,为什么要为Manager.prototype而烦恼呢?

请注意,在构造函数中:

function Employee() {
    this.name = "NoName";
    this.dept = "NoDept";
}

当调用为:

new Employee();

名称和dept 属性将直接添加到分配给此对象的新对象中。它们不是继承的,而是直接在实例上。

在第一个版本中,即使我们不使用原型继承,也可以访问 name 属性

因为当你这样做时:

Employee.call(this);

您正在将名称属性直接添加到管理器的实例中。它不是继承的,而是直接在实例上。

在第二个版本中,我们注释掉了 call(( 并定义了原型链,但 name 属性是无法访问

由于 name 属性不在原型链上,因此 Employee 构造函数将其直接放在其 this 上(这通常是 Employee 的实例,但由于您如何从管理器调用它,它是管理器的实例(。

这让我想知道,那么,为什么要打扰Manager.prototype呢?

因此,管理器的实例将从 Employee.prototype 继承。但是您尚未向 Employee.prototype 添加任何方法,因此没有要继承的内容。

为什么要打扰Manager.prototypeobject.create结合。 因为如果你不使用它,它将不会继承你的基/超类"员工"的原型方法。通常,在实际场景中,您的超类将具有您想要继承的原型方法,在该场景中,object.create 为您提供了一种更简单的方法来实现这一目标。
考虑以下示例

function Employee() {
    this.name = "NoName";
    this.dept = "NoDept";
};
Employee.prototype.method1 = function(){//super class method
 alert("super method");   
}
function Manager() {
    Employee.call(this);//inherit direct properties
    this.reports = "Nobody";
}
Manager.prototype = Object.create(Employee.prototype);//inherit prototype
var m = new Manager();
m.method1();//commenting out object.create will not allow this access