1. JavaScript のオブジェクト
JavaScript はオブジェクトベースのプログラミング言語であると言えます。なぜオブジェクト指向ではなくオブジェクトベースと言われるのでしょうか? JavaScript 自体はカプセル化を実装するだけで、継承とポリモーフィズムを実装していないからです。 。オブジェクトをベースにしているので、js のオブジェクトについて話しましょう。 js のすべてがオブジェクトであると言う人もいますが、これは完全に正しいわけではありません。右側は、彼が js のオブジェクトの重要性を強調したことです。オブジェクト自体を構築できる関数も含め、オブジェクトは js のあらゆる場所に存在します。しかしその一方で、jsには数値、文字列、ブール値、null値、未定義値などの単純なデータ型もいくつかあり、これらはオブジェクトではありません。では、なぜこれらのタイプの値はオブジェクトではないのでしょうか? 結局のところ、これらの値にもメソッドがあります。 JavaScript には 2 つのオブジェクトの定義があるので見てみましょう。
(1) JavaScript のオブジェクトは可変のキー付きコレクションです (この定義はベテランの本の第 3 章から来ています)
(2) JavaScript のオブジェクトは順序付けされていません )、これらの属性には単純なデータ型、オブジェクト、関数を含めることができます; オブジェクトの属性に格納されている関数は、このオブジェクトのメソッドとも呼ばれます。 (ECMA-262 4.3.3 より) (注: ここで説明されているプロパティは、システムによってオブジェクトに自動的に割り当てられる内部プロパティを除き、js スクリプトで作成およびアクセスできます (明示的なプロパティと呼びます))
では、なぜその単純なデータ型はオブジェクトではないのですか?主な理由は、これらのデータ型の値のメソッドは不変ですが、オブジェクトのプロパティは変更可能である必要があるためです。
2. オブジェクト
内のプロトタイプチェーン [[proto]] JavaScript の各オブジェクトが作成されると、システムは自動的にプロトタイプ属性 [[proto]] を割り当てて、そのプロトタイプ オブジェクトに接続します。 JavaScript では、オブジェクトの継承関係は各オブジェクトの [[proto]] によって実現されます。ただし、オブジェクトの [[proto]] 属性は JavaScript でアクセスしたり変更したりすることはできません。これは内部属性として存在し、オブジェクトの作成時にシステムによって自動的に設定されます。
オブジェクトの特定の属性にアクセスするとき、この属性がこのオブジェクトに存在しない場合は、[[proto]] が指すプロトタイプ オブジェクトの属性でそれを検索し、見つかった場合はそれを返し、そうでない場合は続行します。 [[proto]] チェーンは、[[proto]] の接続が null になるまで検索され続けます。
3. 関数もオブジェクトです
JavaScript における関数自体はオブジェクト (そのため、関数オブジェクトと呼ぶことが多いです) であり、js の中で最も重要なオブジェクトであると言えます。これが最も重要なオブジェクトと呼ばれる理由は、一方では他の言語の関数と同じ役割を果たすことができ、呼び出したりパラメーターを渡したりできるためです。オブジェクトのコンストラクターを使用すると、new 演算子と組み合わせてオブジェクトを作成できます。
関数はオブジェクトであるため、オブジェクトの作成時に設定されるプロトタイプ チェーン [[proto]] 属性を含む、オブジェクトのすべてのプロパティが含まれている必要があります。
関数オブジェクトと通常のオブジェクトの違いを見てみましょう。オブジェクトは順序付けされていないプロパティのコレクションであると前に述べましたが、関数のプロパティと通常のオブジェクトのプロパティの違いは何でしょうか? ECMA-262 のセクション 13.2 によると、関数オブジェクトが作成されると、システムは関数オブジェクトが通常の関数として呼び出されるときに、デフォルトで 2 つの属性 [[call]] と [[constructor]] を作成します (たとえば、 myFunc()) の場合、「()」演算子は、関数オブジェクトの [[call]] 属性がコンストラクター (new myConst() など) として呼び出されるときに、その [[constructor The ]] が実行されることを指定します。属性が実行され、[[cosntructor]] の実行プロセスは次のセクションで紹介されます。さらに、関数が作成されると、システムはデフォルトでその表示属性プロトタイプを作成し、それに
This.prototype = {constructor:this}
の値を割り当てます。 詳細については、Lao Dao を参照してください。その本の第5章。この関数オブジェクトのプロトタイプ属性も、js が関数をコンストラクターとして使用して継承を実装するために用意されていますが、この属性は js スクリプト内でアクセスして変更できます。ここで強調すべきことの 1 つは、誰もがオブジェクトの [[proto]] 属性と関数オブジェクトのプロトタイプ属性を区別する必要があるということです。回り道がたくさん。
4. オブジェクトの作成
js でオブジェクトを作成するには 2 つの方法があります。1 つは、
var Person = {
"first_name":'liang',
' のようなリテラルを使用する方法です。 last_name':'yang'
}
もう一つの方法は、コンストラクターを通して作成することです
var my = new Person('liang','yang')
実際には、最初の One メソッドです。作成プロセスの実行は、次のように Object コンストラクターを呼び出すことと同じです。
var person = new Object();
person.first_name = 'liang';
person.last_name = 'yang'
したがって、コンストラクトを使用してすべてのオブジェクトの作成をマージできます。これを達成するには、コンストラクターがオブジェクトを作成するプロセスを詳しく説明します。
最初のステップは、空のオブジェクト (属性なし) を作成し、このオブジェクトの [[proto]] をこのコンストラクターにポイントすることです。コンストラクター関数の
2 番目のステップは、この空のオブジェクトをこのポインターとしてコンストラクター関数に渡し、それを実行することです
3 番目のステップは、上記の関数がオブジェクトを返す場合はオブジェクトを返し、それ以外の場合は作成されたオブジェクトを返します最初のステップ
ステップ 4、関数をクラスとして使用する
上記のステップから、一般的に言えば、関数オブジェクトのプロトタイプは関数オブジェクトではなく通常のオブジェクトを指していることがわかります。この通常のオブジェクトは、この関数コンストラクターによって作成されたオブジェクトからもアクセスできます。これから、次のようにコードを設計できます。このコンストラクター関数によって生成されるオブジェクトが、このクラスのインスタンス オブジェクトであると仮定します。次に、インスタンス オブジェクトに含める必要がある属性とメソッドを配置します。このコンストラクター関数では、このクラスの静的メソッドをオブジェクトの属性としてこの関数に直接配置できます。最後の関数本体は、オブジェクト指向言語で通常コンストラクターと呼ばれるものです。 「コンストラクター」と「コンストラクター関数」という 2 つの単語を区別する必要があります。いわゆるコンストラクターは通常のオブジェクト指向言語のクラスのコンストラクターを指し、コンストラクター関数は JavaScript で使用される関数を指します。コンストラクター)。
セクション 3 で、各関数のプロトタイプ オブジェクトには常にコンストラクター属性が含まれていると述べました。コンストラクター属性は、私たちに接続されている関数そのものです。さらに、この関数によって生成される各オブジェクトの [[proto]] 属性は、コンストラクター関数のプロトタイプ オブジェクトを指すため、[[proto]] チェーンを通じて、コンストラクター関数によって生成される各オブジェクトは、コンストラクター関数の属性ポイントを持ちます。そのため、この属性を使用して、どのコンストラクター関数がこのオブジェクトを生成したかを判断できます。
5. 関数の継承 (クラスの継承)
ここまで述べてきましたが、いよいよ JavaScript での継承について説明します。まず、クラスの継承を実装するために何をする必要があるかを考えてみましょう。サブクラス subClass
subClass によって生成されたオブジェクトが superClass によって生成されたオブジェクトのプロパティにアクセスできるようにするために、subClass.prototype を superClass コンストラクターによって生成されたオブジェクトにすることができます。
subclass.prototye = new superClass();
しかし、セクション 4 で述べたことによると、new superClass() は superClass.prototype 内のすべてのメソッドをコピーするだけでなく、superClass() も実行します。 ) この関数はクラス内のコンストラクターとして機能します。初期化を実装するには、親クラスのコンストラクターをサブクラスのコンストラクターで呼び出す必要があることがわかっています。この目的を達成するには、空のコンストラクターを持つ関数を作成しますが、プロトタイプは superClass プロトタイプと一致し、subClass.prototype がこの関数によって生成されたオブジェクトを指すようにします。
var F = function() {};
F.prototype = superClass.prototype;
subClass.protptype = new F();
このようにして、コンストラクタ 作業内容をコピーします。しかし、別の問題があります。つまり、subClass のプロトタイプ属性を変更してコンストラクター属性を削除したため、どのコンストラクター関数がオブジェクトを生成したかを知ることができなくなりました。
subClass.prototype.constructor = subClass;
このようにして、属性のコピーの問題は簡単に解決されます。しかし、subClass では、その親クラスがどのコンストラクター関数であるかを知ることができないため、コンストラクター内で親クラスのコンストラクターを呼び出すことができないため、それを示す属性を subClass に追加することができます。親クラス
subClass.superClass = superClass.prototype;
このように、サブクラスのコンストラクターで subClass.superClass.constructor を使用して、親クラスのコンストラクターにアクセスできます。最後に、上記のアイデアを関数に記述します。
myPro.extend = function (subClass, superClass) {
var F = function() {};
F.prototype = superClass.prototype; subClass .protptype = new F();
subClass.prototype.constructor = subClass;
superClass.prototype.constructor =
}