Kai*_*Kai 50 javascript constructor prototype
以下代码的作用如下:
WeatherWidget.prototype = new Widget;
Run Code Online (Sandbox Code Playgroud)
哪里Widget是构造函数,我想用新函数扩展Widget'类' WeatherWidget.
什么是new关键字在那里做什么以及如果被遗漏会发生什么?
Poi*_*ars 51
WeatherWidget.prototype = new Widget;
Run Code Online (Sandbox Code Playgroud)
该new关键字调用Widget构造函数,返回值分配给prototype属性.(如果你省略new,Widget除非你添加了一个参数列表,否则你不会调用().但是,调用Widget这种方式可能是不可能的.如果它不是严格模式代码并且实现是实现的,它肯定有可能破坏全局命名空间.符合ECMAScript Ed.5.x那里,因为this在构造函数中会引用ECMAScript的全局对象.)
但是这种方法实际上来自旧的Netscape JavaScript 1.3指南中的一个非常病毒的 坏例子(在Oracle,以前的Sun镜像).
这样,您的WeatherWidget实例将全部继承自同一 Widget实例.原型链将是:
[new WeatherWidget()] ? [new Widget()] ? [Widget.prototype] ? …
Run Code Online (Sandbox Code Playgroud)
这可能很有用,但大多数时候你不希望它发生.除非您希望所有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;
Run Code Online (Sandbox Code Playgroud)
该constructor原型属性应该是固定的为好,这样你的WeatherWidget情况下,w将有w.constructor === WeatherWidget预期,而不是w.constructor === Widget.但是,请注意,之后可以枚举.
这样一来,WeatherWidget情况将通过继承原型链的属性,但它们之间不会分享的属性值,因为它们继承Widget.prototype,通过Dummy它没有自己的属性:
[new WeatherWidget()] ? [new Dummy()] ? [Widget.prototype] ? …
Run Code Online (Sandbox Code Playgroud)
在ECMAScript Ed的实现中.5及以后,你可以而且应该使用
WeatherWidget.prototype = Object.create(Widget.prototype, {
constructor: {value: WeatherWidget}
});
Run Code Online (Sandbox Code Playgroud)
代替.这具有额外的优点,即所得constructor属性不可写,可枚举或可配置.
只有在显式调用父构造函数时,才会调用父构造函数WeatherWidget,例如
function WeatherWidget (…)
{
Widget.apply(this, arguments);
}
Run Code Online (Sandbox Code Playgroud)
另请参阅Function.prototype.extend()我的JSX:object.js,了解如何概括它.使用该代码,它将成为
WeatherWidget.extend(Widget);
Run Code Online (Sandbox Code Playgroud)
我Function.prototype.extend()需要一个可选的第二个参数,您可以使用它轻松扩充WeatherWidget实例的原型:
WeatherWidget.extend(Widget, {
foo: 42,
bar: "baz"
});
Run Code Online (Sandbox Code Playgroud)
相当于
WeatherWidget.extend(Widget);
WeatherWidget.prototype.foo = 42;
WeatherWidget.prototype.bar = "baz";
Run Code Online (Sandbox Code Playgroud)
但是,您仍然需要在子构造函数中显式调用父构造函数; 那部分不能合理地自动化.但我为实例Function.prototype.extend()添加了一个_super属性Function,使其更容易:
function WeatherWidget (…)
{
WeatherWidget._super.apply(this, arguments);
}
Run Code Online (Sandbox Code Playgroud)
其他人已实施类似的扩展.
根据一些奇怪的Javascript规则,new Widget实际上调用构造函数而不是返回对构造函数的引用.这个问题实际上回答了var a = new Widget()和之间的区别var a = Widget().
简单来说,new关键字告诉Javascript Widget在一组不同于常规函数调用的规则下调用函数.脱离我的头脑,我记得的是:
Widget可以使用this关键字来引用该对象.Widget不返回任何内容,则将创建此新对象.Widget用于跟踪属性链的.如果没有new关键字,则会调用窗口小部件
this将设置为undefined.this将引用全局对象.(window由浏览器调用.)undefined返回.参考:
new关键字
WeatherWidget.prototype = new Widget;
Run Code Online (Sandbox Code Playgroud)
确实创建了Widget构造函数的新实例并将其用作WeatherWidget原型对象.使用new关键字创建新对象,设置它的继承链Widget.prototype,并在其上应用构造函数(您可以在其中设置单个属性的'n'方法,或创建私有范围的变量).
没有new关键字,它将是Widget对prototype属性的函数赋值- 这没有任何意义.如果你要添加可选括号(ie Widget()),它会正常调用函数,但不能作为新实例的构造函数,而是将全局对象作为上下文.另请参阅关键字的参考this.
请注意,您不应该真正使用此代码.如上所述,它通过调用构造函数创建一个新实例.但目的只是创建一个从s原型对象继承的空对象Widget,而不是实例化某些东西(这可能会造成一些伤害,具体取决于代码).相反,你应该使用Object.create(或其流行的垫片):
WeatherWidget.prototype = Object.create(Widget.prototype);
Run Code Online (Sandbox Code Playgroud)
另见Javascript基本继承与Crockford原型继承
| 归档时间: |
|
| 查看次数: |
7382 次 |
| 最近记录: |