当前位置: 首页 > 面试题库 >

使用Object.create进行继承的好处

况唯
2023-03-14
问题内容

我一直在努力解决Object.createECMAScript 5中引入的新方法。

通常,当我想使用继承时,我会执行以下操作:

var Animal = function(name) { this.name = name; }
Animal.prototype.print = function() { console.log(this.name); }

var Dog = function() 
{ 
  return Animal.call(this, 'Dog'); 
}

Dog.prototype = new Animal();
Dog.prototype.bark = function() { console.log('bark'); }

我只是将一个新创建的Animal对象分配给Dog的原型,一切都像一个吊饰一样工作:

var dog1 = new Dog();
dog1.print(); // prints 'Dog'
dog1.bark(); // prints 'bark'
dog1.name; //prints 'Dog'

但是人们(没有解释)说这Dog.prototype = new Animal();不是继承的工作方式,我应该使用Object.create方法:

Dog.prototype = Object.create(Animal.prototype);

这也有效。

使用有什么好处,Object.create或者我错过了什么?

更新:有人说也Dog.prototype = Animal.prototype;可以。所以现在我很困惑


问题答案:

在下面的内容中,我假设您仅对为什么Object.create设置继承更好的原因感兴趣。

为了了解其好处,首先让我们澄清一下JavaScript中“类”的组成。您分为两个部分:

  1. 构造 函数。该函数包含创建“类”实例(即实例特定代码)的所有逻辑

  2. 原型 对象。这是实例继承的对象。它包含应在所有实例之间共享的所有方法(和其他属性)。

继承 建立了一个 is-a的 关系,例如,一个Dog 一个Animal。这如何用构造函数和原型对象表达?

显然,狗必须有相同的方法作为一种动物,那就是Dog 原型 对象必须以某种方式合并从方法的Animal 原型
对象。有多种方法可以做到这一点。您会经常看到以下内容:

Dog.prototype = new Animal();

这是有效的,因为Animal 实例是Animal 原型 对象继承的。 但这 也意味着每只狗都从 一个 特定的Animal
实例 继承。这似乎有点奇怪。实例特定的代码不应该仅在 构造 函数中运行吗?突然, 实例 特定的代码和 原型 方法似乎混杂在一起。

那时候我们实际上并不想要运行Animal 实例 特定的代码,我们只希望Animal 原型
对象中的所有方法。那就是Object.create我们要做的:

Dog.prototype = Object.create(Animal.prototype);

在这里,我们 没有 创建新Animal实例,仅获得了原型方法。该 实例 特定代码究竟执行的地方应该是,在构造函数中:

function Dog() { 
   Animal.call(this, 'Dog'); 
}

最大的优点是Object.create始终 有效。使用new Animal()仅在构造函数不期待任何变量工作。想象一下,如果构造函数看起来像这样:

function Animal(name) { 
    this.name = name.toLowerCase();
}

您始终必须将字符串传递给Animal,否则会出现错误。当您这样做时,您会通过什么Dog.prototype = new Animal(??);?传递哪个字符串实际上并不重要,只要传递 某些东西 ,就可以告诉您这是不好的设计。

有人说也Dog.prototype = Animal.prototype;可以。所以现在我很困惑

一切,补充说:“”从属性Animal.prototypeDog.prototype意志的“工作”。但是解决方案的质量不同。在这种情况下,您将遇到一个问题,即您添加到的任何方法Dog.prototype也将被添加到中Animal.prototype

例:

Dog.prototype.bark = function() {
    alert('bark');
};

由于Dog.prototype === Animal.prototype,所有Animal实例bark现在都有一个方法,这当然不是您想要的。

Object.create(甚至new Animal)通过创建一个新对象来向继承添加一个间接级别,该新对象继承自Animal.prototype该对象,并且该新对象成为Dog.prototype

ES6中的继承

ES6引入了一种新语法来创建构造函数和原型方法,如下所示:

class Dog extends Animal {

  bark() {
    alert('bark');
  }

}

这比我上面解释的要方便,但是事实证明,它extends也使用内部等效项Object.create来建立继承。请参阅ES6草案中的步骤2和3 。
这意味着使用Object.create(SuperClass.prototype)是ES5中的“更正确”方法。



 类似资料:
  • 问题内容: 在JavaScript中,这两个示例有什么区别: 先决条件: 使用Object.create的继承示例A: 使用new关键字的继承示例B 这两个例子似乎做同样的事情。您何时会选择一个? 另一个问题:考虑下面链接(第15行)中的代码,其中对函数自己的构造函数的引用存储在原型中。为什么这有用? 摘录(如果您不想打开链接): 问题答案: 在您的问题中,您提到,这根本不是真的,因为 你的第一个

  • 问题内容: 我们对PostgreSQL中的继承以及在JPA中将其映射为实体存在疑问。我们的数据库和我们要映射的表是: 我们在Netbeans 7.1.2中使用自动工具将它们映射到实体。起初我认为仅添加就足够了 因此,它只是 扩大了 ,但无法正常工作。最好的方法是什么?提前致谢。 问题答案: JPA的继承概念基于普通表。它并没有真正“理解” PostgreSQL表继承的想法。这是使用旨在暴露功能的最

  • 错误是... 关于继承和@EqualSandHashCode以及Lombok有没有我正在滥用的最佳实践?或者有什么办法?

  • webresources定义如下。这个类是由NetBeans自动添加的。

  • 将所有服务器都放在一个篮子里的系统管理员是勇敢的(或者说是愚蠢的)。 比方说,你将服务器托管在三个不同的提供商:WreckSpace、GoDodgy 和 VerySlow。 他们有不同的数据中心且分布在不同的地理位置,所以你需要对服务器配置做一些小的改动, 以适应每个提供商。你有几种类型的服务器,它们随机分布在三个不同的提供商。 使用 Puppet 的一种实现方法是在节点定义中设置一个变量用于告知

  • 问题内容: 因此,这些年来,我终于停止拖延脚步,决定“适当”学习JavaScript。语言设计中最令人头疼的元素之一是继承的实现。拥有Ruby的经验,我很高兴看到闭包和动态类型。但是对于我一生来说,无法弄清楚使用其他实例进行继承的对象实例将带来什么好处。 问题答案: 首先,让我们看一下JavaScript程序员在捍卫原型继承中所陈述的最常见的参数(我从当前的答案池中获取这些参数): 这很简单。 功