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

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

问题描述

以下代码执行的操作:

  WeatherWidget.prototype = new Widget; 

其中 Widget 是一个构造函数,想要使用新的函数 WeatherWidget 扩展Widget的类。



<$> c $ c> new 关键字在那里,如果它被遗漏会发生什么?

解决方案

  WeatherWidget.prototype = new Widget; 

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



但这种方法实际上来自真正病毒

在Netscape JavaScript 1.3指南
中, =nofollow noreferrer> p>这样,您的 WeatherWidget 实例将全部继承自相同的 Widget 实例。原型链将是:

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

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



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

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

构造函数以及, WeatherWidget 实例 w 会有 w.constructor === WeatherWidget ,而不是 w.constructor === Widget 。但是,请注意它之后是可枚举的。)



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

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

父构造函数只有在您从 WeatherWidget 中明确调用时才会被调用,例如使用

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

(如果你处在一个非常受限制的环境中,需要符合ECMAScript Ed。 5和更高版本,所以不是在网上 - 或ECMAScript版本5.1的实施已经变得无处不在 - 从现在开始10年左右,考虑到第3版是长期,你可以并应该使用 WeatherWidget.prototype = Object.create (Widget.prototype,{constructor:{value:WeatherWidget}}); 还有一个额外的优点,即所产生的构造函数属性是 not writable,enumerable,or configurable 。)



另请参阅 Function.prototype.extend() 在我的 JSX:object.js 中了解如何推广。使用该代码,它将成为

  WeatherWidget.extend(Widget); 

My Function.prototype.extend()采用可选的第二个参数,您可以轻松地扩充 WeatherWidget 实例的原型:

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

将等同于

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

你仍然需要在子构造函数中显式调用父构造函数;该部分不能合理地自动化。但是我的 Function.prototype.extend() Function 添加了 _super code> instance更容易:

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

其他人已实施类似的扩展。


What does the following code do:

WeatherWidget.prototype = new Widget;

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

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

解决方案

WeatherWidget.prototype = new Widget;

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.)

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

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

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

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.

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;

(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.)

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] → …

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

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

(If you are in a very restricted environment that requires compliance with ECMAScript Ed. 5 and later – so not on the Web – or when implementations of ECMAScript Edition 5.1 have become ubiquitous – in 10 years or so from now, given that it took Edition 3 that long –, you can and should use WeatherWidget.prototype =Object.create(Widget.prototype, {constructor: {value: WeatherWidget}}); instead. This has the additional advantage that the resulting constructor property is not writable, enumerable, or configurable.)

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

WeatherWidget.extend(Widget);

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"
});

would be equivalent to

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

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