次のコードは何をしますか:
WeatherWidget.prototype = new Widget;
whereWidget
はコンストラクターで、Widget の「クラス」を新しい関数で拡張したいと考えていますWeatherWidget
。
キーワードはそこで何をしnew
ており、それが省略された場合はどうなりますか?
次のコードは何をしますか:
WeatherWidget.prototype = new Widget;
whereWidget
はコンストラクターで、Widget の「クラス」を新しい関数で拡張したいと考えていますWeatherWidget
。
キーワードはそこで何をしnew
ており、それが省略された場合はどうなりますか?
WeatherWidget.prototype = new Widget;
new
キーワードがコンストラクターとして呼び出され、Widget
戻り値がプロパティに割り当てられprototype
ます。( を省略すると、引数リスト を追加しない限りnew
呼び出されません。ただし、その方法で呼び出すことはできない可能性があります。厳格モードのコードではなく、実装がそこでは ECMAScript Ed. 5.x に準拠します。これは、コンストラクターで ECMAScript のグローバル オブジェクトを参照するためです。)Widget
()
Widget
this
しかし、このアプローチは実際には、古い Netscape JavaScript 1.3 ガイド(以前の Sun である Oracle にミラーリングされています)の非常にバイラル な悪い例から来ています。
このようにして、インスタンスはすべて同じWeatherWidget
インスタンスから継承されます。プロトタイプ チェーンは次のようになります。 Widget
[new WeatherWidget()] → [new Widget()] → [Widget.prototype] → …
これは便利ですが、ほとんどの場合、これが発生することは望ましくありません。すべてのWeatherWidget
インスタンスが、このインスタンスから継承するプロパティ値を共有する場合を除き、ここでそれを行うべきではありません。もう 1 つの問題は、この方法で親コンストラクターを呼び出す必要があることです。この方法では、引数なしで呼び出すことができないか、適切に初期化されない可能性があります。これは、Java などで知られているクラスベースの継承のエミュレーションとはまったく関係ありません。Widget
Widget.prototype
これらのプロトタイプベースの言語でクラスベースの継承を実装する適切な方法は次のとおりです (もともとは、2003 年にラッセ ライヒシュタイン ニールセンがcomp.lang.javascript
オブジェクトの複製のために考案したものです)。
function Dummy () {}
Dummy.prototype = Widget.prototype;
WeatherWidget.prototype = new Dummy();
WeatherWidget.prototype.constructor = WeatherWidget;
constructor
プロトタイプ プロパティも修正する必要がありWeatherWidget
ます。ただし、後で列挙可能であることに注意してください。w
w.constructor === WeatherWidget
w.constructor === Widget
このように、インスタンスはプロトタイプ チェーンを介しWeatherWidget
てプロパティを継承しますが、独自のプロパティを持たないから継承するため、インスタンス間でプロパティ値を共有しません。Widget.prototype
Dummy
[new WeatherWidget()] → [new Dummy()] → [Widget.prototype] → …
ECMAScript Edの実装。5以降では、使用できますし、使用する必要があります
WeatherWidget.prototype = Object.create(Widget.prototype, {
constructor: {value: WeatherWidget}
});
代わりは。constructor
これには、結果のプロパティが書き込み可能、列挙可能、または構成可能ではないという追加の利点があります。
WeatherWidget
親コンストラクターは、 fromなどで明示的に呼び出した場合にのみ呼び出されます
function WeatherWidget (…)
{
Widget.apply(this, arguments);
}
Function.prototype.extend()
これを一般化する方法については、私のJSX:object.jsも参照してください。そのコードを使用すると、
WeatherWidget.extend(Widget);
Myは、インスタンスFunction.prototype.extend()
のプロトタイプを簡単に拡張できるオプションの 2 番目の引数を取ります。WeatherWidget
WeatherWidget.extend(Widget, {
foo: 42,
bar: "baz"
});
と同等です
WeatherWidget.extend(Widget);
WeatherWidget.prototype.foo = 42;
WeatherWidget.prototype.bar = "baz";
ただし、子コンストラクターで明示的に親コンストラクターを呼び出す必要があります。その部分は合理的に自動化できません。しかし、インスタンスにプロパティをFunction.prototype.extend()
追加すると、簡単になります。_super
Function
function WeatherWidget (…)
{
WeatherWidget._super.apply(this, arguments);
}
他の人も同様の拡張機能を実装しています。
いくつかの奇妙な 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;
Widget
コンストラクターの新しいインスタンスを作成し、それをWeatherWidget
のプロトタイプ オブジェクトとして使用します。new
キーワードを使用して新しいオブジェクトを作成し、その継承チェーンを にセットアップしWidget.prototype
、コンストラクター関数を適用します (ここで、個々のプロパティのメソッドをセットアップするか、プライベート スコープの変数を作成できます)。
new
キーワードがなければWidget
、プロパティへの関数の割り当てになりprototype
ます - これは意味がありません。オプションの括弧 (つまりWidget()
) を追加すると、関数が通常どおり呼び出されますが、新しいインスタンスのコンストラクターとしてではなく、グローバル オブジェクトをコンテキストとして呼び出します。キーワードのリファレンスthis
も参照してください。
このコードは実際には使用しないでください。前述のように、コンストラクター関数を呼び出して新しいインスタンスを作成します。ただし、目的はs プロトタイプ オブジェクトから継承する空のWidget
オブジェクトを作成することだけであり、何かをインスタンス化することではありません (コードによっては、何らかの害を及ぼす可能性があります)。代わりに、Object.create
(またはその人気のある shim)を使用する必要があります。
WeatherWidget.prototype = Object.create(Widget.prototype);
Javascript の基本的な継承と Crockford のプロトタイプの継承も参照してください。
平易な英語では、あるクラスを別のクラスに拡張しています。プロトタイプはオブジェクトにしかできないため、WeatherWidget
のプロトタイプを の新しいインスタンスに設定しますWidget
。キーワードを削除するnew
と、何もしないリテラル コンストラクター関数にプロトタイプを設定することになります。
var Appendages = function(){
this.legs = 2
};
var Features = function() {
this.ears = 4;
this.eyes = 1;
}
// Extend Features class with Appendages class.
Features.prototype = new Appendages;
var sara = new Features();
sara.legs;
// Returns 2.
プロトタイプが任意のオブジェクトである可能性があることを理解すると、次のようなものも機能します。
var appendages = {
legs : 2
};
var Features = function() {
this.ears = 4;
this.eyes = 1;
}
// Extend Features class with Appendages class.
Features.prototype = appendages;
var sara = new Features();
sara.legs;
// Returns 2.
JavaScript では、オブジェクトにキーが見つからない場合、拡張元の親オブジェクトをチェックします。したがって、次のように、その場で親オブジェクトのアイテムを変更できます。
var appendages = {
legs : 2
};
var Features = function() {
this.ears = 4;
this.eyes = 1;
}
// Extend Features class with Appendages class.
Features.prototype = appendages;
var sara = new Features();
sara.legs;
// Returns 2.
appendages.hair = true;
sara.hair;
// Returns true.
これはすべてインスタンス化中に発生することに注意してください。つまり、オブジェクトを作成した後にプロトタイプを切り替えることはできません。
var foo = {name : 'bob'};
var bar = {nachos : 'cheese'};
foo.prototype = bar;
foo.nachos;
// undefined
ただし、最近のすべてのブラウザーには、この新しい__proto__
方法が付属しており、それを行うことができます。
var foo = {name : 'bob'};
var bar = {nachos : 'cheese'};
foo.__proto__ = bar;
foo.nachos
// "cheese"
JavaScript プロトタイプの理解について詳しくは、こちらをご覧ください。Pivotal Labs のこの記事も非常に優れています。
new
プロトタイプの継承にとって重要です。つまり
、メソッドでコンストラクターを作成します
var Obj = function(){};
Obj.prototype = {};
Obj.prototype.foo = function(){console.log('foo');};
最初のコンストラクターを拡張する 2 番目のコンストラクターを作成します。
var ExObj = function(){};
ここで、 なしでプロトタイプを作成するnew
と、
ExObj.prototype = Obj;
(new ExObj).foo(); // TypeError: Object #<Object> has no method 'foo'
これは、 のプロトタイプから継承していないことを意味しますがObj
、new
ExObj.prototype = new Obj();
(new ExObj).foo(); // console logs 'foo'
さらに、 のプロトタイプに新しいものを追加しても、そのExObj
ベースであるObj
.
JavaScript 関数は "MULTIPLE(2) PERSONALITIES" です!!!
それらは入力と出力を持つ通常の関数であり、 のように呼び出しますfunction()
。
new
また、キーワードを使用すると、JS オブジェクトのコンストラクターになります。>>>しかし<<< 新しく作成されたオブジェクトは、コンストラクターのインスタンスではありません (クラスベースの継承におけるクラスのオブジェクトのように)。prototype
新しいオブジェクトは、コンストラクターのプロパティのオブジェクトのインスタンスです。
次にWeatherWidget.prototype =
、コンストラクターが作成するオブジェクトにプロパティを継承するオブジェクトを配置します。これは通常new function()
、関数ではなく関数です。
JavaScript は、コンストラクターによって作成されたオブジェクトの名前をinstanceof
キーワードでインスタンス化することにより、プログラミング コミュニティに大きな混乱を引き起こしました。
> function f(){}
undefined
> new f() instanceof f
true