JavaScript自体はオブジェクト指向であり、これら「シミュレートされたオブジェクト指向」が実際に行うことは「シミュレートされた
クラスベースのオブジェクト指向」です。JavaScript の創始者であるブレンダン・アイヒは、 「プロトタイプ ランタイム」をベースにnew や this などの言語機能を導入したことで、「構文がより Java に似ている」ようになり、Java はクラスベースのオブジェクト指向言語の代表的な言語の 1 つになりました。
さまざまなプログラミング言語で、デザイナーはさまざまな言語機能を使用してオブジェクトを抽象的に記述します。
1. 最も成功したジャンルは、オブジェクトを記述するために「クラス」を使用することであり、C++ や Java などの人気のあるプログラミング言語を生み出しました
。このジャンルはクラスベースのプログラミング言語と呼ばれます。2.プロトタイプを使用してオブジェクトを記述するプロトタイプベースのプログラミング言語もあります。私たちの JavaScript はその 1 つです。
「クラスベース」プログラミング:
「クラスベース」プログラミングでは、カテゴリとクラス間の関係に焦点を当てた開発モデルの使用が推奨されます。そのような言語では、常に最初に
クラスがあり、次にクラスからオブジェクトがインスタンス化されます。クラス と クラスの間には、継承や合成などの関係が形成される場合があります。多くの場合、クラスは
言語の型システムと統合されて、特定のコンパイル時の機能を形成します。
「プロトタイプベース」のプログラミング:
「プロトタイプベース」のプログラミングでは、プログラマーが一連のオブジェクト インスタンスの動作に注意を払い、これらのオブジェクトをクラスに分割するのではなく、同様の使用法を持つ最も近いプロトタイプ オブジェクトに分割する方法に注意を払うことをより提唱しているようです。
プロトタイプベースのオブジェクト指向システムは、「コピー」によって新しいオブジェクトを作成します。
一部の言語実装では、null オブジェクトのコピーも許可されています。これは本質的に、まったく新しいオブジェクトを作成することです。
プロトタイプ システムの「コピー操作」を実現するには、次の 2 つの方法があります。
1. 1 つはプロトタイプ オブジェクトを実際にコピーするのではなく、新しいオブジェクトにプロトタイプへの参照を保持させること
2. もう 1 つは実際にオブジェクトをコピーすることであり、2 つのオブジェクトはもはや関連していません。
このように、歴史的にプロトタイプベースの言語は 2 つの考え方を生み出してきましたが、JavaScript は明らかに前者を選択しました。
JavaScript のプロトタイプ:
プロトタイプ システムは非常に単純であると言えますが、2 つの一般化を使用できます:
1. すべてのオブジェクトがプライベート フィールド [[prototype]] を持っている場合、それはオブジェクトのプロトタイプです;
2. プロパティを読み取る場合、オブジェクトがプロトタイプが空になるか見つかるまでオブジェクトにアクセスし続けます。
ES6 以降、JavaScript は一連の組み込み関数を提供して、プロトタイプの操作により直接アクセスできるようにしました。
Object.createは指定されたプロトタイプに従って新しいオブジェクトを作成し、プロトタイプは null にすることができます;
Object.getPrototypeOf はオブジェクトのプロトタイプを取得します;
Object.setPrototypeOf はオブジェクトのプロトタイプを設定します。//下面的代码展示了用原型来抽象猫和虎的例子。 //创建一个“猫”对象 var cat = { say(){ console.log("meow~"); }, jump(){ console.log("jump"); } } //根据猫做了一些修改创建了虎 var tiger = Object.create(cat, { say:{ writable:true, configurable:true, enumerable:true, value:function(){ console.log("roar!"); } } }) //可以用Object.create 来创建另外的猫和虎对象 //我们可以通过“原始猫对象”和“原始虎对象”来控制所有猫和虎的行为。 var anotherCat = Object.create(cat); anotherCat.say(); var anotherTiger = Object.create(tiger); anotherTiger.say();
新しい操作は正確には何をしますか:
新しい操作は、コンストラクターと一連の呼び出しパラメーターを受け入れ、実際にいくつかのことを行います
。 2. this を渡してパラメーターをコンストラクターに呼び出して実行する; 3. コンストラクターがオブジェクトを返す場合はそれを返し、そうでない場合は最初のステップで作成されたオブジェクトを返します。new の動作は、客観的に次の 2 つの方法を提供します。
1 つは、コンストラクターにプロパティを追加することです。
2 つ目は、コンストラクターのプロトタイプ プロパティにプロパティを追加することです。
次のコードは、コンストラクターを使用してクラスをシミュレートする2 つの方法を示しています。
//第一种方法是直接在构造器中修改 this,给 this 添加属性。 function c1(){ this.p1 = 1; this.p2 = function(){ console.log(this.p1); } } var o1 = new c1; o1.p2(); //第二种方法是修改构造器的 prototype 属性指向的对象 //它是从这个构造器构造出来的所有对象的原型。 function c2(){ } c2.prototype.p1 = 1; c2.prototype.p2 = function(){ console.log(this.p1); } var o2 = new c2; o2.p2();
ES6 のクラス - クラス:
クラスの基本的な書き方:
class Rectangle { constructor(height, width) { this.height = height; this.width = width; } // Getter get area() { return this.calcArea(); } // Method calcArea() { return this.height * this.width; } }
We create getter through get/set keyword, and create methods throughかっこと中かっこ. データ メンバーは、
コンストラクターで記述するのが最適です。
クラスは継承機能を提供します。
//创造了 Animal 类 class Animal { constructor(name) { this.name = name; } speak() { console.log(this.name + ' makes a noise.'); } } //通过 extends 关键字让 Dog 继承 Animal class Dog extends Animal { constructor(name) { super(name); // call the super class constructor and pass in the name parameter } speak() { console.log(this.name + ' barks.'); } } //调用子类的 speak 方法获取了父类的 name。 let d = new Dog('Mitzie'); d.speak(); // Mitzie barks.
したがって、クラスの考え方を使用してコードを設計する場合、古い構文を使用して関数でオブジェクトをシミュレートするのではなく、クラスを使用してクラスを宣言するように努める必要があります。