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

查看:33
本文介绍了在 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<继承的 属性值,否则您不应该在此处这样做/code> 实例,并且仅通过它,来自 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的没有自己属性的虚拟:

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天全站免登陆