在 Derived.prototype = new Base 中使用“new"关键字的原因是什么 [英] What is the reason to use the 'new' keyword at Derived.prototype = new Base

查看:29
本文介绍了在 Derived.prototype = new Base 中使用“new"关键字的原因是什么的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下代码有什么作用:

WeatherWidget.prototype = new Widget;

其中 Widget 是一个构造函数,我想用一个新函数 WeatherWidget 扩展 Widget 'class'.

where Widget is a constructor, and I want to extend the Widget 'class' with a new function WeatherWidget.

new 关键字在那里做什么?如果省略它会发生什么?

What is the new keyword doing there and what would happen if it is left out?

推荐答案

WeatherWidget.prototype = new Widget;

new 关键字调用 Widget 作为构造函数,并将返回值分配给 prototype 属性.(如果省略new,则不会调用Widget,除非添加了参数列表().但是,调用Widget 这种方式可能是不可能的.如果它不是严格模式代码并且实现符合 ECMAScript Ed. 5.x,它肯定有可能破坏全局命名空间,因为构造函数中的 this 会引用 ECMAScript 的全局对象.)

The new keyword calls Widget as a constructor and the return value is assigned to the prototype property. (If you would omit new, you would not call Widget unless you added an argument list, (). However, calling Widget that way might not be possible. It would certainly have the potential to spoil the global namespace if it is not strict mode code and the implementation is conforming to ECMAScript Ed. 5.x there, because then this in the constructor would refer to ECMAScript’s global object.)

但这种方法实际上来自于真的病毒 坏例子 在旧的 Netscape JavaScript 1.3 指南(反映在 Oracle,前身为 Sun).

But this approach actually comes from a really viral bad example in the old Netscape JavaScript 1.3 Guide (mirrored at Oracle, formerly Sun).

这样,您的 WeatherWidget 实例都将从 same Widget 实例继承.原型链将是:

This way, your WeatherWidget instances will all inherit from the same Widget instance. The prototype chain will be:

[new WeatherWidget()] → [new Widget()] → [Widget.prototype] → …

这可能很有用,但大多数时候您不希望它发生.您不应该在这里这样做,除非您希望所有 WeatherWidget 实例在它们之间共享属性值,它们从这个 Widget 实例,并且只有 通过它,来自 Widget.prototype.另一个问题是您需要以这种方式调用父构造函数,这可能不允许像您一样在没有参数的情况下调用,或者无法正确初始化.它当然与已知的基于类的继承的模拟无关,例如来自 Java.

This can be useful, but most of the time you would not want it to happen. You should not do that here unless you want all your WeatherWidget instances to share among them the property values they inherit from this Widget instance, and only through it, from Widget.prototype. Another problem is that you need to call the parent constructor this way, which may not allow to be called without arguments as you do, or would not initialize properly. It certainly has nothing to do with emulation of class-based inheritance as known, e.g., from Java.

在这些基于原型的语言中实现基于类的继承的正确方法是(最初由 Lasse Reichstein Nielsen 于 2003 年在 comp.lang.javascript 中用于克隆对象):

The proper way to implement class-based inheritance in these prototype-based languages is (originally devised by Lasse Reichstein Nielsen in comp.lang.javascript in 2003, for cloning objects):

function Dummy () {}
Dummy.prototype = Widget.prototype;
WeatherWidget.prototype = new Dummy();
WeatherWidget.prototype.constructor = WeatherWidget;

constructor 原型属性也应该是固定的,这样你的 WeatherWidget 实例 w 就会有 w.constructor === WeatherWidget 符合预期,而不是 w.constructor === Widget.但是,请注意它在之后是可枚举的.

The constructor prototype property should be fixed as well, so that your WeatherWidget instances w would have w.constructor === WeatherWidget as expected, and not w.constructor === Widget. However, be aware that it is enumerable afterwards.

这样,WeatherWidget 实例将通过原型链继承属性,但不会在它们之间共享属性值,因为它们从Widget.prototype 通过 继承Dummy 没有自己的属性:

This way, WeatherWidget instances will inherit properties through the prototype chain, but will not share property values among them, because they inherit from Widget.prototype through Dummy which has no own properties:

[new WeatherWidget()] → [new Dummy()] → [Widget.prototype] → …

在 ECMAScript Ed 的实现中.5 及更高版本,您可以并且应该使用

In implementations of ECMAScript Ed. 5 and later, you can and should use

WeatherWidget.prototype = Object.create(Widget.prototype, {
  constructor: {value: WeatherWidget}
});

相反.这具有额外的优势,即结果 constructor 属性是 不可写、不可枚举或可配置.

instead. This has the additional advantage that the resulting constructor property is not writable, enumerable, or configurable.

父构造函数只有在你显式调用时才会被调用,从WeatherWidget,例如

The parent constructor will only be called if you call it explicitly, from WeatherWidget, for example with

function WeatherWidget (…)
{
  Widget.apply(this, arguments);
}

另见Function.prototype.extend() 在我的 JSX:object.js 关于如何概括这一点.使用该代码,它会变成

See also Function.prototype.extend() in my JSX:object.js for how to generalize this. Using that code, it would become

WeatherWidget.extend(Widget);

我的 Function.prototype.extend() 接受一个可选的第二个参数,您可以使用它轻松扩充 WeatherWidget 实例的原型:

My Function.prototype.extend() takes an optional second argument with which you can easily augment the prototype of WeatherWidget instances:

WeatherWidget.extend(Widget, {
  foo: 42,
  bar: "baz"
});

相当于

WeatherWidget.extend(Widget);
WeatherWidget.prototype.foo = 42;
WeatherWidget.prototype.bar = "baz";

不过,您仍然需要在子构造函数中显式调用父构造函数;该部分不能合理地自动化.但是我的 Function.prototype.extend()Function 实例添加了一个 _super 属性,这使它更容易:

You will still need to call the parent constructor explicitly in the child constructor, though; that part cannot reasonably be automated. But my Function.prototype.extend() adds a _super property to the Function instance which makes it easier:

function WeatherWidget (…)
{
  WeatherWidget._super.apply(this, arguments);
}

其他人已经实现了类似的扩展.

Other people have implemented similar extensions.

这篇关于在 Derived.prototype = new Base 中使用“new"关键字的原因是什么的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆