/* Alex Arnell の継承実装に基づいています。 */
var Class = (function() {
//親のプロトタイプを一時的に保存します
function subclass() {} ;
//クラスを作成するメソッド
function create() {
varparent = null,properties = $A(arguments); //クラスを作成するときに指定するかどうかを確認します。 new class 親オブジェクト
//親クラスが指定されている場合は、値を親に代入します
if (Object.isFunction(properties[0]))
parent = property.shift(); >
//インスタンスの作成時に実際に返されるクラスで、初期化のために初期化メソッドが呼び出されます。
function klass() {
this.initialize.apply(this, argument); >}
//create メソッドを呼び出した後、addMethods メソッドを klass に追加します
//クラスレベルのメソッド展開のために addMethods メソッドを呼び出すこともできます
Object.extend(klass, Class .Methods);
// 返されたクラスに 2 つの属性を追加します。スーパークラス: 親クラス、サブクラス: サブクラスのコレクション
klass.subclasses = []; 🎜>//クラスを作成する場合 親オブジェクトを指定した場合、klassのプロトタイプに親オブジェクトのインスタンスを指し、プロトタイプチェーンの継承を実装します。
if (parent) {
subclass.prototype =parent.プロトタイプ;
klass.prototype = new subclass;
// 親クラスにサブクラスを追加し、親クラスのサブクラス コレクションを維持します
parent.subclasses.push(klass); >
//新しいクラスにメソッドを追加します
for (var i = 0; i
klass.addMethods(properties[i]); //初期化メソッドが指定されていない場合は、デフォルトで空のメソッドが使用されます。 初期化メソッドに代入します。
if (!klass.prototype.initialize)
klass.prototype.initialize = Prototype.emptyFunction
;
/*
* コンストラクターがそれ自体を指すように、新しいクラスのコンストラクターを修正します。ここで特に注意してください (次の行をコメントアウトした場合):
* var Person=Class. create();
* var p1=new person();
* alter(p1.constructor==person) //true
* var Man=Class.create(person)
* var m1=new Man();
*alert(m1.constrcutor==Man) //false
*alert(m1.constrcutor==person) //true
*alert(m1.constructor== p1.constrcutor) //true
*
* 問題が分かりましたか? Man のコンストラクターは実際には Person のコンストラクターを指しています
※ 問題の根源は klass.prototype = new subclass;
※ 詳しい理由は説明しませんので、「JavaScript 言語」を参照してください。本質とプログラミング実践』155~160ページ
*/
klass.prototype.constructor = klass;
return klass;
}
//クラス作成時にメソッドを追加新しいクラスに追加するか、クラスの作成後にクラスレベルのメソッドを追加します。
function addMethods(source) {
//新しいクラスの親クラスを取得します
var ancestor = this.superclass && this. superclass.prototype;
varproperties = Object.keys(source);
//なぜこのように書かれているのかわかりません。 、教えてください?
if (!Object .keys({ toString: true }).length) {
//新しいクラスが toString メソッドと valueOf メソッドをオーバーライドする場合、それらを追加します
if (source.toString != Object.prototype.toString)
properties.push("toString");
if (source.valueOf != Object.prototype.valueOf)
properties.push("valueOf"); >}
//新しいクラス宣言内のすべてのメソッドを走査します
for (var i = 0, length = property.length; i
//property は関数名、値は関数本体です
var property = property[i], value = source[property]
//このメソッドが親クラスの同じ名前のメソッドを呼び出す必要があるかどうかを決定します if (ancestor && Object.isFunction(value) &&
value.argumentNames ().first() == "$super") {
var Method = value;
//これは非常に重要です。
//このパラメータが親クラスの同じ名前のメソッドを指すように、$super パラメータを置き換えます。
//ここでは Function の Wrap メソッドを使用します。 Wrap メソッドの説明については、を参照してください。 to [プロトタイプ学習 - 関数オブジェクト]
/ /method は新しく定義されたメソッドなので、最初のパラメータは $super で、'=' から '.' までに返されるのはその同じ名前のメソッドです。親クラス
//最後に、ラップ メソッドを呼び出して $super を配置します。パラメータを親クラスの同じ名前のメソッドに置き換えます。これにより、サブクラスが $super() を呼び出したときに、同じ名前のメソッドが呼び出されます。親クラスは
と呼ばれます // ここの構造は素晴らしいです!Worth thinking about
value = (function(m) {
return function() { return ancestor[m].apply(this, arguments); };
})(property).wrap(method);
//Point the valueOf and toString of the newly generated value (i.e. the modified subclass method) to the method of the same name of the atomic class
🎜>value.valueOf = method.valueOf.bind(method);
value.toString = method.toString.bind(method);
}
//Add the method to the new class
this.prototype[property] = value;
}
return this;
}
//Return the callable method of Class
return {
create: create,
Methods: {
addMethods: addMethods
}
};
})();
This class provides 2 methods: create and addMethods, which are clearly explained in the source code comments above. Let’s look at some examples to explain the usage in detail: