オブジェクトの継承
オブジェクト指向プログラミングの非常に重要な側面は、オブジェクトの継承です。オブジェクト B を継承することにより、オブジェクト A はオブジェクト B のすべてのプロパティとメソッドを直接所有できます。これはコードを再利用する場合に非常に役立ちます。
ほとんどのオブジェクト指向プログラミング言語は、「クラス」を通じてオブジェクトの継承を実装します。従来、JavaScript 言語の継承はクラスではなく、「プロトタイプ オブジェクト」によって実装されていました。この章では、JavaScript のプロトタイプ チェーンの継承について説明します。
ES6 ではクラス構文が導入されました。クラスベースの継承はこのチュートリアルでは紹介されていません。『ES6 標準入門』の関連する章を参照してください。
プロトタイプ オブジェクトの概要
コンストラクターの欠点
JavaScript はコンストラクターを通じて新しいオブジェクトを生成するため、コンストラクターはオブジェクトのテンプレートと考えることができます。インスタンス オブジェクトのプロパティとメソッドはコンストラクター内で定義できます。
関数 Cat (名前、色) {
this.name = 名前;
this.color = 色;
}
var cat1 = new Cat('大きな髪', '白');
cat1.name // 'ビッグヘアー'
cat1.color // '白'
上記のコードでは、Cat
関数はコンストラクターであり、name
属性と color
属性が関数内で定義されており、すべてのインスタンス オブジェクト (上の例は cat1
) がこれら 2 つの属性を生成します。つまり、これら 2 つの属性はインスタンス オブジェクトで定義されます。
コンストラクターを通じてインスタンス オブジェクトのプロパティを定義するのは便利ですが、欠点もあります。同じコンストラクターの複数のインスタンス間でプロパティを共有できないため、システム リソースが無駄に消費されます。
関数 Cat(名前, 色) {
this.name = 名前;
this.color = 色;
this.meow = function () {
console.log('ニャー');
};
}
var cat1 = new Cat('大きな髪', '白');
var cat2 = new Cat('二毛', 'black');
猫1.ニャー === 猫2.ニャー
// 間違い
上記のコードでは、cat1
と cat2
は同じコンストラクターの 2 つのインスタンスであり、両方とも meow
メソッドを持っています。 meow
メソッドは各インスタンスオブジェクトに対して生成されるため、2つのインスタンスが2回生成されます。つまり、新しいインスタンスが作成されるたびに、新しい meow
メソッドが作成されます。すべての「meow」メソッドは同じ動作をし、共有する必要があるため、これは不必要であり、システム リソースの無駄でもあります。
この問題を解決するのが JavaScript のプロトタイプ オブジェクトです。
プロトタイププロパティの役割
JavaScript 継承メカニズムの設計上の考え方は、プロトタイプ オブジェクトのすべてのプロパティとメソッドをインスタンス オブジェクトで共有できるということです。つまり、プロトタイプでプロパティとメソッドが定義されている場合、すべてのインスタンス オブジェクトを共有できるため、メモリが節約されるだけでなく、インスタンス オブジェクト間の接続も反映されます。
次に、オブジェクトのプロトタイプを指定する方法を見てみましょう。 JavaScript では、各関数がオブジェクトを指す「prototype」属性を持つことを規定しています。
関数 f() {}
typeof f.prototype // "オブジェクト"
上記のコードでは、関数 f
はデフォルトでオブジェクトを指す prototype
属性を持っています。
通常の関数では、この属性は基本的には役に立ちません。ただし、コンストラクターの場合、インスタンスが生成されると、このプロパティは自動的にインスタンス オブジェクトのプロトタイプになります。
関数 動物(名前) {
this.name = 名前;
}
Animal.prototype.color = '白';
var cat1 = 新しい動物('ビッグヘア');
var cat2 = new Animal('二毛');
cat1.color // '白'
cat2.color // '白'
上記のコードでは、コンストラクター Animal
の prototype
属性は、インスタンス オブジェクト cat1
および cat2
のプロトタイプ オブジェクトです。プロトタイプ オブジェクトに「color」プロパティを追加すると、その結果、すべてのインスタンス オブジェクトがこのプロパティを共有します。
プロトタイプ オブジェクトのプロパティは、インスタンス オブジェクト自体のプロパティではありません。プロトタイプ オブジェクトを変更すると、その変更は すべて インスタンス オブジェクトに即座に反映されます。
Animal.prototype.color = '黄色';
cat1.color // "黄色"
cat2.color // "黄色"
上記のコードでは、プロトタイプ オブジェクトの color
属性の値が yellow
に変更され、2 つのインスタンス オブジェクトの color
属性が即座に変更されます。これは、インスタンス オブジェクトには実際には color
属性がなく、プロトタイプ オブジェクトの color
属性が読み取られるためです。つまり、インスタンス オブジェクト自体が特定のプロパティやメソッドを持たない場合、プロトタイプ オブジェクトにアクセスしてプロパティやメソッドを見つけます。これがプロトタイプ オブジェクトの特別な点です。
インスタンス オブジェクト自体に特定のプロパティまたはメソッドがある場合、プロトタイプ オブジェクト内でそのプロパティまたはメソッドは検索されません。
cat1.color = '黒';
cat1.color // '黒'
cat2.color // '黄色'
Animal.prototype.color // '黄色';
上記のコードでは、インスタンス オブジェクト cat1
の color
属性が black
に変更されるため、プロトタイプ オブジェクトから color
属性が読み取られなくなり、後者の値は yellow のままになります。
。
要約すると、プロトタイプ オブジェクトの役割は、すべてのインスタンス オブジェクトで共有されるプロパティとメソッドを定義することです。これがプロトタイプ オブジェクトと呼ばれる理由であり、インスタンス オブジェクトはプロトタイプ オブジェクトから派生したサブオブジェクトとみなすことができます。
Animal.prototype.walk = function () {
console.log(this.name + ' は歩いています');
};
上記のコードでは、「walk」メソッドが「Animal.prototype」オブジェクトで定義されており、すべての「Animal」インスタンス オブジェクトで呼び出すことができます。
プロトタイプチェーン
JavaScript では、すべてのオブジェクトが独自のプロトタイプ オブジェクト (プロトタイプ) を持つことを規定しています。一方で、任意のオブジェクトは他のオブジェクトのプロトタイプとして機能できますが、他方では、プロトタイプ オブジェクトもオブジェクトであるため、独自のプロトタイプもあります。したがって、オブジェクトからプロトタイプ、そしてプロトタイプのプロトタイプ…という「プロトタイプ チェーン」が形成されます。
これを層ごとに追跡すると、すべてのオブジェクトのプロトタイプは最終的に Object.prototype
、つまり Object
コンストラクターの prototype
属性にまで遡ることができます。言い換えれば、すべてのオブジェクトは Object.prototype
のプロパティを継承します。すべてのオブジェクトに valueOf
メソッドと toString
メソッドがあるのはこのためです。これは Object.prototype
から継承されているためです。
では、Object.prototype
オブジェクトにはプロトタイプがあるのでしょうか?答えは、「Object.prototype」のプロトタイプが「null」であるためです。 「null」にはプロパティやメソッドはなく、独自のプロトタイプもありません。したがって、プロトタイプ チェーンの最後は「null」になります。
Object.getPrototypeOf(Object.prototype)
// null
上記のコードは、Object.prototype
オブジェクトのプロトタイプが null
であることを示しています。 null
には属性がないため、プロトタイプ チェーンはここで終了します。 Object.getPrototypeOf
メソッドはパラメータ オブジェクトのプロトタイプを返します。詳細については、次の記事を参照してください。
オブジェクトの特定の属性を読み取るとき、JavaScript エンジンはまずオブジェクト自体の属性を探します。それでも見つからない場合は、プロトタイプのプロトタイプに進みます。最上位の Object.prototype
が見つからない場合は、unknown
が返されます。オブジェクト自体とそのプロトタイプの両方が同じ名前のプロパティを定義している場合、オブジェクト自体のプロパティが最初に読み取られます。これを「オーバーライド」と呼びます。
1 レベル上のプロトタイプ チェーン全体で特定の属性を検索すると、パフォーマンスに影響することに注意してください。探しているプロパティが上位レベルのプロトタイプ オブジェクト内にあるほど、パフォーマンスへの影響が大きくなります。存在しないプロパティを探す場合は、プロトタイプ チェーン全体が走査されます。
たとえば、コンストラクターの prototype
属性が配列を指している場合、インスタンス オブジェクトが配列メソッドを呼び出すことができることを意味します。
var MyArray = function () {};
MyArray.prototype = 新しい Array();
MyArray.prototype.constructor = MyArray;
varmine = new MyArray();
私のもの.push(1, 2, 3);
Mine.length // 3
私のインスタンスの配列 // true
上記のコードでは、mine
はコンストラクター MyArray
のインスタンス オブジェクトです。 MyArray.prototype
は配列インスタンスを指しているため、mine
は配列メソッドを呼び出すことができます (これらのメソッドは、コンストラクター MyArray
の prototype
オブジェクトで定義されています)。配列インスタンス) 。 instanceof
式の最後の行は、オブジェクトが特定のコンストラクターのインスタンスであるかどうかを比較するために使用され、その結果、mine
が Array
のインスタンスであることが証明されます。 、 以下を参照してください。
上記のコードは、プロトタイプ オブジェクトの constructor
属性も示しています。この属性の意味については、次のセクションで説明します。
コンストラクター プロパティ
prototype
オブジェクトには constructor
プロパティがあり、デフォルトでは prototype
オブジェクトが配置されているコンストラクターを指します。
関数 P() {}
P.prototype.constructor === P // true
constructor
プロパティは prototype
オブジェクトに定義されているため、すべてのインスタンス オブジェクトに継承できることを意味します。
関数 P() {}
var p = 新しい P();
p.constructor === P // true
p.constructor === P.prototype.constructor // true
p.hasOwnProperty('constructor') // false
上記のコードでは、p
はコンストラクター関数 P
のインスタンス オブジェクトですが、p
自体には constructor
プロパティがありません。このプロパティは実際にはプロトタイプの P.prototype.constructor
プロパティを読み取ります。鎖。
constructor
属性の目的は、どのコンストラクターが特定のインスタンス オブジェクトを生成したかを知ることです。
関数 F() {};
var f = 新しい F();
f.constructor === F // true
f.constructor === RegExp // false
上記のコードでは、constructor
属性によって、インスタンス オブジェクト f
のコンストラクターが RegExp
ではなく F
であることが決定されます。
一方、constructor
プロパティを使用すると、インスタンス オブジェクトから別のインスタンスを作成できます。
関数 Constr() {}
var x = 新しい Constr();
var y = 新しい x.constructor();
y インスタンスオブ Constr // true
上記のコードでは、x
はコンストラクター Constr
のインスタンスであり、コンストラクターは x.constructor
から間接的に呼び出すことができます。これにより、インスタンス メソッド内から独自のコンストラクターを呼び出すことが可能になります。
Constr.prototype.createCopy = function () {
新しい this.constructor() を返します。
};
上記のコードでは、createCopy
メソッドがコンストラクターを呼び出して別のインスタンスを作成します。
constructor
属性は、プロトタイプ オブジェクトとコンストラクターの関係を表します。プロトタイプ オブジェクトが変更されると、参照時のエラーを防ぐために、通常は constructor
属性も同時に変更されます。
関数 人(名前) {
this.name = 名前;
}
Person.prototype.constructor === 人物 // true
人物.プロトタイプ = {
メソッド: 関数 () {}
};
Person.prototype.constructor === 人物 // false
Person.prototype.constructor === オブジェクト // true
上記のコードでは、コンストラクター person
のプロトタイプ オブジェクトが変更されていますが、constructor
属性は変更されていないため、この属性は person
を指さなくなります。 person
の新しいプロトタイプは通常のオブジェクトであり、通常のオブジェクトの constructor
プロパティは Object
コンストラクターを指しているため、person.prototype.constructor
は Object
になります。
したがって、プロトタイプ オブジェクトを変更するときは、通常、同時に constructor
属性のポインティングを変更する必要があります。
//書き方が悪い
C. プロトタイプ = {
メソッド1: 関数 (...) { ... },
// ...
};
// 良い書き方
C. プロトタイプ = {
コンストラクター: C、
メソッド1: 関数 (...) { ... },
// ...
};
// より良い書き方
C.prototype.method1 = function (...) { ... };
上記のコードでは、constructor
属性を元のコンストラクターにリダイレクトするか、プロトタイプ オブジェクトにメソッドのみを追加して、instanceof
演算子が歪められないようにします。
constructor
属性がどのような関数であるかわからない場合は、別の方法があります。それは、name
属性を使用してインスタンスからコンストラクターの名前を取得することです。
関数 Foo() {}
var f = 新しい Foo();
f.constructor.name // "フー"
インスタンスオブ演算子
「instanceof」演算子は、オブジェクトがコンストラクターのインスタンスであるかどうかを示すブール値を返します。
var v = 新しい車両();
v インスタンスの車両 // true
上記のコードでは、オブジェクト v
はコンストラクター Vehicle
のインスタンスであるため、true
を返します。
instanceof
演算子の左側はインスタンス オブジェクト、右側はコンストラクターです。右コンストラクターのプロトタイプ オブジェクトが左オブジェクトのプロトタイプ チェーン上にあるかどうかを確認します。したがって、次の 2 つの書き方は同等です。
v Vehicle のインスタンス
// と同等
Vehicle.prototype.isPrototypeOf(v)
上記のコードでは、Vehicle
はオブジェクト v
のコンストラクターであり、そのプロトタイプ オブジェクトは Vehicle.prototype
です。 isPrototypeOf()
メソッドは、JavaScript によって提供されるネイティブ メソッドです。 object は別のオブジェクトです。オブジェクトのプロトタイプについては後で詳しく説明します。
instanceof
はプロトタイプ チェーン全体をチェックするため、同じインスタンス オブジェクトが複数のコンストラクターに対して true
を返す場合があります。
var d = 新しい日付();
dinstanceof Date // true
d オブジェクトのインスタンス // true
上記のコードでは、d
は Date
と Object
の両方のインスタンスであるため、両方のコンストラクターは true
を返します。
あらゆるオブジェクト (「null」を除く) は「Object」のインスタンスであるため、「instanceof」演算子は値が非「null」オブジェクトであるかどうかを判断できます。
var obj = { foo: 123 };
obj オブジェクトのインスタンス // true
null オブジェクトのインスタンス // false
上記のコードでは、他のオブジェクトに対する「instanceOf Object」の演算結果は、「null」を除いてすべて「true」になります。
instanceof
の原理は、右側のコンストラクターの prototype
属性が左側のオブジェクトのプロトタイプ チェーン上にあるかどうかをチェックすることです。左側のオブジェクトのプロトタイプ チェーンに「null」オブジェクトのみが存在する特殊なケースがあります。このとき、「インスタンス」の判断が歪められることになる。
var obj = Object.create(null);
typeof obj // "オブジェクト"
obj オブジェクトのインスタンス // false
上記のコードでは、Object.create(null)
は、プロトタイプが null
である新しいオブジェクト obj
を返します (Object.create()
の詳細については、以下を参照してください)。右側のコンストラクター Object
の prototype
属性は左側のプロトタイプ チェーンにないため、instanceof
は obj
が Object
のインスタンスではないとみなします。これは、「instanceof」演算子の評価が歪む唯一のケースです (オブジェクトのプロトタイプが「null」です)。
「instanceof」演算子の使用法の 1 つは、値の型を決定することです。
var x = [1, 2, 3];
var y = {};
x 配列のインスタンス // true
y オブジェクトのインスタンス // true
上記のコードでは、「instanceof」演算子は、変数「x」が配列であり、変数「y」がオブジェクトであると判断します。
「instanceof」演算子はオブジェクトに対してのみ使用でき、プリミティブ型の値には使用できないことに注意してください。
vars = 'こんにちは';
sinstanceof String // false
上記のコードでは、文字列は String
オブジェクトのインスタンスではないため (文字列はオブジェクトではないため)、false
が返されます。
さらに、「instanceof」演算子は、「unknown」および「null」に対して常に「false」を返します。
未定義のオブジェクトのインスタンス // false
null オブジェクトのインスタンス // false
instanceof
演算子を使用すると、コンストラクターを呼び出すときに new
コマンドを追加し忘れるという問題を賢く解決することもできます。
関数 Fubar (foo, bar) {
if (Fubar のこのインスタンス) {
this._foo = foo;
this._bar = バー;
} それ以外 {
新しい Fubar(foo, bar) を返します。
}
}
上記のコードは、「instanceof」演算子を使用して、「this」キーワードが関数本体内のコンストラクター「Fubar」のインスタンスであるかどうかを判断します。そうでない場合は、「new」コマンドを追加するのを忘れたことを意味します。
コンストラクターの継承
あるコンストラクターが別のコンストラクターを継承することは、非常に一般的な要件です。これは 2 つのステップで実現できます。最初のステップは、サブクラスのコンストラクターで親クラスのコンストラクターを呼び出すことです。
関数サブ(値) {
Super.call(this);
this.prop = 値;
}
上記のコードでは、Sub
はサブクラスのコンストラクターであり、this
はサブクラスのインスタンスです。インスタンス上で親クラスのコンストラクター「Super」を呼び出すと、子クラスのインスタンスが親クラスのインスタンスの属性を持つようになります。
2 番目のステップは、サブクラスのプロトタイプが親クラスのプロトタイプを指すようにして、サブクラスが親クラスのプロトタイプを継承できるようにすることです。
Sub.prototype = Object.create(Super.prototype);
Sub.prototype.constructor = サブ;
Sub.prototype.method = '...';
上記のコードでは、Sub.prototype
はサブクラスのプロトタイプであり、Super.prototype
と直接等しいのではなく、値 Object.create(Super.prototype)
を割り当てる必要があります。それ以外の場合、次の 2 行の Sub.prototype
に対する操作は、親クラスのプロトタイプ Super.prototype
を一緒に変更します。
別の書き方では、Sub.prototype
が親クラスのインスタンスと等しいということです。
Sub.prototype = 新しい Super();
上記の書き方でも継承の効果はありますが、サブクラスは親クラスのインスタンスのメソッドを持つことになります。場合によっては、これが必要なものではない可能性があるため、この書き方を使用することはお勧めできません。
たとえば、これは Shape
コンストラクターです。
functionShape() {
this.x = 0;
this.y = 0;
}
Shape.prototype.move = 関数 (x, y) {
this.x += x;
this.y += y;
console.info('図形が移動しました。');
};
Rectangle
コンストラクターを Shape
から継承させる必要があります。
// 最初のステップでは、サブクラスは親クラスのインスタンスを継承します。
関数 Rectangle() {
Shape.call(this); // 親クラスのコンストラクターを呼び出します。
}
// 別の書き方
関数 Rectangle() {
this.base = 形状;
this.base();
}
//第 2 ステップでは、サブクラスが親クラスのプロトタイプを継承します。
Rectangle.prototype = Object.create(Shape.prototype);
Rectangle.prototype.constructor = 長方形;
この書き込みメソッドを使用した後、「instanceof」演算子はサブクラスと親クラスの両方のコンストラクターに対して「true」を返します。
var rect = 新しい Rectangle();
rectinstanceof Rectangle // true
rectinstanceofShape // true
上記のコードでは、サブクラスは親クラスを全体として継承します。 1 つのメソッドの継承だけが必要な場合もあります。この場合は、次の記述方法を使用できます。
ClassB.prototype.print = function() {
ClassA.prototype.print.call(this);
// 何らかのコード
}
上記のコードでは、サブクラス B
の print
メソッドが最初に親クラス A
の print
メソッドを呼び出してから、独自のコードをデプロイします。これは、親クラス A
の print
メソッドを継承することに相当します。
多重継承
JavaScript は多重継承を提供しません。つまり、1 つのオブジェクトが同時に複数のオブジェクトを継承することはできません。ただし、この機能を実現するための回避策はあります。
関数 M1() {
this.hello = 'こんにちは';
}
関数 M2() {
this.world = 'ワールド';
}
関数 S() {
M1.call(this);
M2.call(this);
}
//M1を継承
S.prototype = Object.create(M1.prototype);
// M2 を継承チェーンに追加します
Object.assign(S.prototype, M2.prototype);
//コンストラクタを指定
S.prototype.constructor = S;
var s = 新しい S();
s.hello // 'こんにちは'
s.world // 'ワールド'
上記のコードでは、サブクラス S
は親クラス M1
と M2
の両方を継承します。このモードはミックスインとも呼ばれます。
モジュール
Web サイトが「インターネット アプリケーション」になるにつれて、Web ページに埋め込まれた JavaScript コードはより大きく、より複雑になります。 Web ページはますますデスクトップ プログラムに似てきており、チームの分業とコラボレーション、進捗管理、単体テストなどが必要になります。開発者はソフトウェア エンジニアリング手法を使用して Web ページのビジネス ロジックを管理する必要があります。
JavaScript でのモジュール型プログラミングが緊急のニーズとなっています。理想的には、開発者はコア ビジネス ロジックのみを実装する必要があり、他のモジュールは他の人がロードできるようになります。
ただし、JavaScript はモジュール型プログラミング言語ではなく、「クラス」と「モジュール」のサポートが開始されたのは ES6 だけです。以下では、オブジェクトを使用してモジュール効果を実現する方法の従来のアプローチを紹介します。
基本的な実装方法
モジュールは、特定の機能を実装するプロパティとメソッドのセットをカプセル化したものです。
簡単な方法は、モジュールをオブジェクトとして記述し、すべてのモジュール メンバーをこのオブジェクトに入れることです。
var module1 = 新しいオブジェクト({
_カウント: 0、
m1: 関数 (){
//...
}、
m2:関数(){
//...
}
});
上記の関数 m1
と m2
は、module1
オブジェクトにカプセル化されています。使用すると、このオブジェクトのプロパティが呼び出されます。
module1.m1();
ただし、この書き方ではモジュールのメンバーがすべて公開されてしまい、内部状態が外部によって上書きされる可能性があります。たとえば、外部コードは内部カウンターの値を直接変更できます。
module1._count = 5;
プライベート変数のカプセル化: コンストラクターの書き方
コンストラクターを使用してプライベート変数をカプセル化できます。
関数 StringBuilder() {
var バッファ = [];
this.add = 関数 (str) {
バッファ.プッシュ(str);
};
this.toString = function () {
returnbuffer.join('');
};
}
上記のコードでは、buffer
はモジュールのプライベート変数です。インスタンスオブジェクトが生成されると、外部から「buffer」に直接アクセスすることはできなくなります。ただし、このメソッドはコンストラクター内のプライベート変数をカプセル化するため、コンストラクターとインスタンス オブジェクトが統合され、常にメモリ内に存在し、使用後にクリアできなくなります。これは、コンストラクターには、インスタンス オブジェクトの形成とインスタンス オブジェクトのデータの保存という二重の役割があることを意味します。これは、コンストラクターとインスタンス オブジェクト (つまり、インスタンス オブジェクトのデータ) 間のデータ分離の原則に違反します。インスタンス オブジェクトの外部に保存しないでください)。同時に、メモリを非常に消費します。
関数 StringBuilder() {
this._buffer = [];
}
StringBuilder.prototype = {
コンストラクター: StringBuilder、
追加: 関数 (str) {
this._buffer.push(str);
}、
toString: function () {
return this._buffer.join('');
}
};
このメソッドはプライベート変数をインスタンス オブジェクトに配置するため、より自然に見えるという利点がありますが、プライベート変数は外部から読み書きできるため、あまり安全ではありません。
プライベート変数のカプセル化: すぐに実行される関数の作成方法
もう 1 つのアプローチは、「Immediately-Invoked Function Expression (IIFE)」を使用して関連するプロパティとメソッドを関数スコープにカプセル化し、プライベート メンバーを公開しないという目的を達成することです。
var module1 = (関数() {
var_count = 0;
var m1 = 関数 () {
//...
};
var m2 = 関数 () {
//...
};
戻る {
m1 : m1、
平方メートル : 平方メートル
};
})();
上記の書き方では、外部コードから内部の_count
変数を読み込むことができません。
console.info(module1._count); //未定義
上記の「module1」がJavaScriptモジュールの基本的な書き方です。次に、この書き込みメソッドを処理していきます。
モジュールの増幅モード
モジュールが非常に大きく、いくつかの部分に分割する必要がある場合、または 1 つのモジュールが別のモジュールを継承する必要がある場合は、「拡張モード」を使用する必要があります。
var module1 = (関数 (mod){
mod.m3 = 関数 () {
//...
};
モジュールを返します。
})(モジュール1);
上記のコードは、新しいメソッド m3()
を module1
モジュールに追加し、新しい module1
モジュールを返します。
ブラウザ環境では、モジュールの一部が Web から取得されることが多く、どの部分が最初に読み込まれるかを知る方法がない場合があります。上記の記述方法を使用すると、最初に実行される部分で存在しない空のオブジェクトが読み込まれる可能性があり、その場合は「緩やかな拡張モード」を使用する必要があります。
var module1 = (関数 (mod) {
//...
モジュールを返します。
})(window.module1 || {});
「拡大モード」と比較して、「ワイド拡大モード」は「即時実行関数」のパラメータが空のオブジェクトであってもよいことを意味します。
グローバル変数を入力します
独立性はモジュールの重要な機能です。モジュール内のプログラムの他の部分と直接対話しないことが最善です。
モジュール内からグローバル変数を呼び出すには、他の変数をモジュールに明示的に入力する必要があります。
var module1 = (関数 ($, YAHOO) {
//...
})(jQuery、YAHOO);
上記の「module1」モジュールは jQuery ライブラリと YUI ライブラリを使用する必要があるため、これら 2 つのライブラリ (実際には 2 つのモジュール) をパラメータとして「module1」に入力します。これにより、モジュールの独立性が確保されるだけでなく、モジュール間の依存関係も明確になります。
関数の即時実行は名前空間としても機能します。
(関数($, ウィンドウ, ドキュメント) {
関数 go(num) {
}
関数ハンドルイベント() {
}
関数初期化() {
}
関数 dieCarouselDie() {
}
//グローバルスコープにアタッチします
window.finalCarousel = {
init: 初期化、
破壊する:dieCarouselDie
}
})(jQuery、ウィンドウ、ドキュメント);
上記のコードでは、finalCarousel
オブジェクトがグローバル世界に出力され、init
および destroy
インターフェイスが外部世界に公開されます。内部メソッド go
、handleEvents
、initialize
、およびdieCarouselDie
は外部から呼び出すことはできません。
参考リンク
- JavaScript モジュール: 初心者ガイド、Preethi Kasireddy 著
作者: wangdoc
アドレス: https://wangdoc.com/
ライセンス: クリエイティブ・コモンズ 3.0