ここでは、JS の流暢さに関して少しずれていることがいくつかあります (それは問題ありません。4.0 のベース言語機能を離れるとすぐに、私の C# はかなりハックニーになります)。
まず、絶対に避けることをお勧めdocument.write
しますか?
これには技術的な理由があり、ブラウザは最近それらを回避しようと懸命に努力していますが、それでもどこにでも配置するのと同じくらい悪い考えalert()
です (反復を含む)。
Windows のシステム メッセージ ポップアップがいかに煩わしいものであるかは、誰もが知っています。
Chrome を使用している場合は、ヒットCTRL+Shift+J
すると便利なコンソールが表示console.log()
され、(オブジェクト/配列/関数であっても) データセット/DOM オブジェクトのトラバース可能なノードと、他のタイプの文字列を返すことができます (機能)。最近の JS の最も優れた機能の 1 つは、IDE がブラウザー内にあるという事実です。
ゼロから作成して .js ファイルを保存することは、コンソールから特に簡単ではありませんが、テスト/デバッグはこれほど簡単ではありません。
さて、実際の問題に移ります。
例 #1 で何をしているのか見てみましょう。.prototype.constructor
いくつかのエッジケースのブラウザ/エンジンが存在しない限り、の書き換えはまったく不要です。
コンストラクターとして使用される (つまり、 で呼び出される) 関数の内部ではnew
、関数は基本的に新しい object を作成し、それを、 setting 、および settingに{}
割り当てます。this
this.__proto__ = arguments.callee.prototype
this.__proto__.constructor = arguments.callee
arguments.callee === function
var Working = function () {};
var working = new Working();
console.log(working instanceof Working); // [log:] true
Working
は文字列ではありません: 関数にしています。
実際、JS では、window
(ブラウザでは) のプロパティでもあります。
window.Working === Working; // true
window["Working"] === Working; // true
最後の 1 つは、例 2 のジレンマを解決するための鍵です。
ただし、#2 を見る前に注意点があり
ます。大量の疑似サブクラス化を行っている場合は、
var Shape = function () {
this.get_area = function () { };
},
Square = function (w) {
this.w = w;
Shape.call(this);
};
Square と Shape の両方で動作するようにしたい場合instanceof
は、何をどのように継承したいかによって、プロトタイプやコンストラクターをいじり始める必要があります。
var Shape = function () {};
Shape.prototype.getArea = function () { return this.length * this.width; };
var Square = function (l) { this.length = l; this.width = l; };
Square.prototype = new Shape();
var Circle = function (r) { this.radius = r; };
Circle.prototype = new Shape();
Circle.prototype.getArea = function () { return 2 * Math.PI * this.radius; };
var circle = new Circle(4),
square = new Square(4);
circle instanceof Shape; // true
square instanceof Shape; // true
これは単純に、(すべてのインスタンスで再利用される) プロトタイプ オブジェクトを親クラスの新しいインスタンスに設定しているためです。その単一インスタンスをすべての子クラスで共有することもできます。
var shape = new Shape();
Circle.prototype = shape;
Square.prototype = shape;
... をオーバーライドしないでください。.getArea
プロトタイプの継承は public-static メソッドを継承するようなものだからです。
形状はもちろん、それなりshape.__proto__.constructor === Shape
に揃っていsquare.__proto__.constructor === Square
ます。関数が指定されたものと一致するかどうかを確認して、リンクを再帰するinstanceof
だけです。__proto__
そして、上記の方法で関数を構築している場合 (Circle.prototype = new Shape(); Circle.prototype.getArea = function () { /* overriding Shape().getArea() */};
は、それcircle instanceof Circle && circle instanceof Shape
自体を処理します。
ミックスイン継承、または疑似コンストラクター ( でないオブジェクトを返すthis
など) はconstructor
、これらのチェックを機能させるためにマングリングを必要とします。
...とにかく... #2へ:
上記のすべてを知っていれば、これはすぐに修正できるはずです。
関数自体を作成するのではなく、関数の目的の名前の文字列を作成しており、Obj
変数が定義されていないため、「参照エラー」が発生しています。代わりに、「目的の名前」をオブジェクトのプロパティ。
var classes = {},
class_name = "Circle",
constructors = [];
classes[class_name] = function (r) { this.radius = r; };
constructors.push(classes.Circle);
var circle = new constructors[0](8);
circle instanceof classes.Circle;
これですべてが適切に定義され、上書きする必要のないものは上書きされず、 のメンバーをサブクラス化してオーバーライド.prototype
することができ、手続き的な方法 (オブジェクトのプロパティとしてinstanceof
代入し、設定する) で行うことができます。data.name
その値をnew Function(data.args, data.constructor)
に渡し、そのオブジェクト プロパティをルックアップに使用します)。
これの一部/すべてが役立つことを願っています。