1. オブジェクト指向ファクトリメソッド
function createPerson(name, age, job){ var o = new Object(); o.name = name; o.age = age; o.job = job; o.sayName = function(){ alert(this.name); }; return o; } var person1 = createPerson("Nicholas", 29, "Software Engineer"); var person2 = createPerson("Greg", 27, "Doctor"); person1.sayName(); //"Nicholas" person2.sayName(); //"Greg"
ファクトリ モデル方式の欠点は、重複コードが大量に生成されることです。
2. コンストラクター パターンはオブジェクトを作成します
function Person(name, age, job){ this.name = name; this.age = age; this.job = job; this.sayName = function(){ alert(this.name); }; } var person1 = new Person("Nicholas", 29, "Software Engineer"); var person2 = new Person("Greg", 27, "Doctor"); person1.sayName(); //"Nicholas" person2.sayName(); //"Greg" alert(person1 instanceof Object); //true alert(person1 instanceof Person); //true alert(person2 instanceof Object); //true alert(person2 instanceof Person); //true alert(person1.constructor == Person); //true alert(person2.constructor == Person); //true alert(person1.sayName == person2.sayName); //false
new キーワードを使用してオブジェクトを作成するには、次の 4 つのプロセスを経ます
3. コンストラクターを関数として使用します
function Person(name, age, job){ this.name = name; this.age = age; this.job = job; this.sayName = function(){ alert(this.name); }; } var person = new Person("Nicholas", 29, "Software Engineer"); person.sayName(); //"Nicholas" Person("Greg", 27, "Doctor"); //adds to window window.sayName(); //"Greg" var o = new Object(); Person.call(o, "Kristen", 25, "Nurse"); o.sayName(); //"Kristen"
関数として使用する場合、コンストラクターは通常の関数と変わりません。これは、window オブジェクトの下に追加される単なるメソッドです。コンストラクターによって作成されたオブジェクトは実際には新しいオブジェクトを作成するため、この 2 つは本質的に異なり、分離されており、メソッドも依然として異なります。
4. 共通の方法を使用して、矛盾した問題をグローバルに解決します
function Person(name, age, job){ this.name = name; this.age = age; this.job = job; this.sayName = sayName; } function sayName(){ alert(this.name); } var person1 = new Person("Nicholas", 29, "Software Engineer"); var person2 = new Person("Greg", 27, "Doctor"); person1.sayName(); //"Nicholas" person2.sayName(); //"Greg" alert(person1 instanceof Object); //true alert(person1 instanceof Person); //true alert(person2 instanceof Object); //true alert(person2 instanceof Person); //true alert(person1.constructor == Person); //true alert(person2.constructor == Person); //true alert(person1.sayName == person2.sayName); //true
上記のメソッドは同じ問題を解決しますが、定義されたグローバル メソッド自体はウィンドウに属しているため、ローカルとグローバルの間に分離はありません。したがって、この方法はほとんど使用されません。どちらもお勧めしません。
5. プロトタイプモード
私たちが作成する関数にはプロトタイプ オブジェクトがあります。この属性はオブジェクトを指すポインターであり、このオブジェクトの機能は、特定の型のすべてのインスタンスで共有できるメソッドを持つことです。
function Person(){ } Person.prototype.name = "Nicholas"; Person.prototype.age = 29; Person.prototype.job = "Software Engineer"; Person.prototype.sayName = function(){ alert(this.name); }; var person1 = new Person(); person1.sayName(); //"Nicholas" var person2 = new Person(); person2.sayName(); //"Nicholas" alert(person1.sayName == person2.sayName); //true alert(Person.prototype.isPrototypeOf(person1)); //true alert(Person.prototype.isPrototypeOf(person2)); //true //only works if Object.getPrototypeOf() is available if (Object.getPrototypeOf){ alert(Object.getPrototypeOf(person1) == Person.prototype); //true alert(Object.getPrototypeOf(person1).name); //"Nicholas" }
プロトタイプを理解する
関数が作成されるたびに、関数のプロトタイプ オブジェクトを指すプロトタイプ プロパティが作成されます。デフォルトでは、プロトタイプ オブジェクトにはコンストラクター (コンストラクター属性) が含まれます。このコンストラクターには、プロトタイプ属性が配置されている関数へのポインターが含まれます。
属性の読み取り順序
コードはオブジェクトのプロパティを読み取るたびに、指定された名前のプロパティから検索を実行します (存在する場合)。そうでない場合は、プロトタイプ チェーンの最外層が検索されるまで、オブジェクトの検索が続けられます。
function Person(){ } Person.prototype.name = "Nicholas"; Person.prototype.age = 29; Person.prototype.job = "Software Engineer"; Person.prototype.sayName = function(){ alert(this.name); }; var person1 = new Person(); var person2 = new Person(); person1.name = "Greg"; alert(person1.name); //"Greg" 来自实例 alert(person2.name); //"Nicholas" 来自原型
この要素のインスタンス属性が削除された場合
function Person(){ } Person.prototype.name = "Nicholas"; Person.prototype.age = 29; Person.prototype.job = "Software Engineer"; Person.prototype.sayName = function(){ alert(this.name); }; var person1 = new Person(); var person2 = new Person(); person1.name = "Greg"; alert(person1.name); //"Greg" ?from instance alert(person2.name); //"Nicholas" ?from prototype delete person1.name; alert(person1.name); //"Nicholas" - from the prototype
6. hasOwnProperty メソッド
このメソッドは、プロパティがインスタンスに存在するかプロトタイプに存在するかを検出できます。 hasOwnProperty は Object から継承され、指定されたプロパティがオブジェクト インスタンスに存在する限り true を返します。
function Person(){ } Person.prototype.name = "Nicholas"; Person.prototype.age = 29; Person.prototype.job = "Software Engineer"; Person.prototype.sayName = function(){ alert(this.name); }; var person1 = new Person(); var person2 = new Person(); alert(person1.hasOwnProperty("name")); //false alert("name" in person1); //true person1.name = "Greg"; alert(person1.name); //"Greg" ?from instance alert(person1.hasOwnProperty("name")); //true alert("name" in person1); //true alert(person2.name); //"Nicholas" ?from prototype alert(person2.hasOwnProperty("name")); //false alert("name" in person2); //true delete person1.name; alert(person1.name); //"Nicholas" - from the prototype alert(person1.hasOwnProperty("name")); //false alert("name" in person1); //true
7. Object.keys() 列挙可能プロパティ メソッド
このメソッドはパラメータとしてオブジェクトを受け取り、すべての列挙可能なプロパティを含む文字列配列を返します
function Person(){ } Person.prototype.name = "Nicholas"; Person.prototype.age = 29; Person.prototype.job = "Software Engineer"; Person.prototype.sayName = function(){ alert(this.name); }; var keys = Object.keys(Person.prototype); alert(keys); //"name,age,job,sayName" 如果想得到所有实例的属性,无论它是否可以枚举都可以使用这个方法来获取 function Person(){ } Person.prototype.name = "Nicholas"; Person.prototype.age = 29; Person.prototype.job = "Software Engineer"; Person.prototype.sayName = function(){ alert(this.name); }; var keys = Object.getOwnPropertyNames(Person.prototype); alert(keys); //"constructor,name,age,job,sayName"
このメソッドは、上位バージョンのブラウザでのみサポートされています
8. 簡単なプロトタイプの書き方
function Person(){ } Person.prototype = { name : "Nicholas", age : 29, job: "Software Engineer", sayName : function () { alert(this.name); } }; var friend = new Person(); alert(friend instanceof Object); //true alert(friend instanceof Person); //true alert(friend.constructor == Person); //false alert(friend.constructor == Object); //true
プロトタイプの書き換えは、デフォルトのプロトタイプ メソッドを上書きすることと同じであり、同じ構築メソッドも書き換えられ、書き換えられた構築メソッドは Object オブジェクトを指します。元のオブジェクト Person
の代わりに前のコンストラクターをまだ参照したい場合は、それを明示的に指定できます
function Person(){ } Person.prototype = { constructor : Person, name : "Nicholas", age : 29, job: "Software Engineer", sayName : function () { alert(this.name); } }; var friend = new Person(); alert(friend instanceof Object); //true alert(friend instanceof Person); //true alert(friend.constructor == Person); //true alert(friend.constructor == Object); //false
9. プロトタイプメソッドの動的追加
function Person(){ } Person.prototype = { constructor: Person, name : "Nicholas", age : 29, job : "Software Engineer", sayName : function () { alert(this.name); } }; var friend = new Person(); Person.prototype.sayHi = function(){ alert("hi"); }; friend.sayHi(); //"hi" ?works!
10. ネイティブオブジェクトのプロトタイプメソッド
alert(typeof Array.prototype.sort); //"function" alert(typeof String.prototype.substring); //"function" String.prototype.startsWith = function (text) {//修改原生对象的原型方法 return this.indexOf(text) == 0; }; var msg = "Hello world!"; alert(msg.startsWith("Hello")); //true
11. コンストラクターとプロトタイプ パターンの組み合わせを使用してオブジェクトを作成します
//构造函数模式 function Person(name, age, job){ this.name = name; this.age = age; this.job = job; this.friends = ["Shelby", "Court"]; } //原型模式 Person.prototype = { constructor: Person, sayName : function () { alert(this.name); } }; var person1 = new Person("Nicholas", 29, "Software Engineer"); var person2 = new Person("Greg", 27, "Doctor"); person1.friends.push("Van"); alert(person1.friends); //"Shelby,Court,Van" alert(person2.friends); //"Shelby,Court" alert(person1.friends === person2.friends); //false alert(person1.sayName === person2.sayName); //true
12. 動的プロトタイプモード
function Person(name, age, job){ //properties this.name = name; this.age = age; this.job = job; //methods if (typeof this.sayName != "function"){ Person.prototype.sayName = function(){ alert(this.name); }; } } var friend = new Person("Nicholas", 29, "Software Engineer"); friend.sayName();
13. 寄生コンストラクターパターン
function Person(name, age, job){ var o = new Object();//依赖全局对象初始化一个对象,然后再返回这个对象 o.name = name; o.age = age; o.job = job; o.sayName = function(){ alert(this.name); }; return o; } var friend = new Person("Nicholas", 29, "Software Engineer"); friend.sayName(); //"Nicholas" function SpecialArray(){ //create the array var values = new Array(); //add the values values.push.apply(values, arguments); //assign the method values.toPipedString = function(){ return this.join("|"); }; //return it return values; } var colors = new SpecialArray("red", "blue", "green"); alert(colors.toPipedString()); //"red|blue|green" alert(colors instanceof SpecialArray);
アピール メソッドについて少し説明します。このメソッドは外部オブジェクトに依存して新しいオブジェクトを作成するため、instanceof メソッドに依存してプロパティとメソッドのソースを決定することはできません。実際にはコンストラクターとは何の関係もありません。
14. 安全なコンストラクターパターン
function Person(name, age, job){ var o = new Object(); o.sayName = function(){ alert(name); }; return o; } var friend = Person("Nicholas", 29, "Software Engineer"); friend.sayName(); //"Nicholas"
このメソッドは、新しい this キーワードに依存しません。オブジェクトのメソッドとプロパティにアクセスしたい場合は、オブジェクトが定義したメソッドを通じてのみ取得できます。
15. 継承
JavaScript はプロトタイプ チェーンを介して継承を実装します
function SuperType(){ this.property = true;//定义一个属性 } SuperType.prototype.getSuperValue = function(){//定义的原型方法 return this.property; }; function SubType(){ this.subproperty = false; } //inherit from SuperType SubType.prototype = new SuperType(); SubType.prototype.getSubValue = function (){ return this.subproperty; }; var instance = new SubType(); alert(instance.getSuperValue()); //true alert(instance instanceof Object); //true alert(instance instanceof SuperType); //true alert(instance instanceof SubType); //true alert(Object.prototype.isPrototypeOf(instance)); //true alert(SuperType.prototype.isPrototypeOf(instance)); //true alert(SubType.prototype.isPrototypeOf(instance)); //true SubType继承SuperType的方法和属性,因此当instance可以直接调用SuperType的方法! function SuperType(){ this.property = true; } SuperType.prototype.getSuperValue = function(){ return this.property; }; function SubType(){ this.subproperty = false; } //inherit from SuperType SubType.prototype = new SuperType(); //new method SubType.prototype.getSubValue = function (){ return this.subproperty; }; //override existing method SubType.prototype.getSuperValue = function (){ return false; }; var instance = new SubType(); alert(instance.getSuperValue()); //false
上記の例は、オーバーライドされたプロトタイプが以前に継承されたプロトタイプを上書きし、返される最終結果は多くの場合予期した効果ではないことを示しています
function SuperType(){ this.property = true; } SuperType.prototype.getSuperValue = function(){ return this.property; }; function SubType(){ this.subproperty = false; } //inherit from SuperType SubType.prototype = new SuperType(); //使用字面量添加的方法导致上面的方法失效了 SubType.prototype = { getSubValue : function (){ return this.subproperty; }, someOtherMethod : function (){ return false; } }; var instance = new SubType(); console.log(instance); alert(instance.getSuperValue()); //error!
次の例は、プロトタイプの書き換えのリスクも示しています
function SuperType(){ this.colors = ["red", "blue", "green"]; } function SubType(){ } //inherit from SuperType SubType.prototype = new SuperType(); var instance1 = new SubType(); instance1.colors.push("black"); alert(instance1.colors); //"red,blue,green,black" var instance2 = new SubType(); alert(instance2.colors); //"red,blue,green,black"
原型共享导致两个不同的对象调用的同一个数据
16、借用构造函数来实现继承
function SuperType(){ this.colors = ["red", "blue", "green"]; } function SubType(){ //inherit from SuperType SuperType.call(this); } var instance1 = new SubType(); instance1.colors.push("black"); alert(instance1.colors); //"red,blue,green,black" var instance2 = new SubType(); alert(instance2.colors); //"red,blue,green"
传递参数
function SuperType(name){ this.name = name; } function SubType(){ //inherit from SuperType passing in an argument SuperType.call(this, "Nicholas"); //instance property this.age = 29; } var instance = new SubType(); alert(instance.name); //"Nicholas"; alert(instance.age); //29
17、组合继承方式
function SuperType(name){ this.name = name; this.colors = ["red", "blue", "green"]; } SuperType.prototype.sayName = function(){ alert(this.name); }; function SubType(name, age){ SuperType.call(this, name); this.age = age; }
18、原型继承
function object(o){ function F(){} F.prototype = o; return new F(); } var person = { name: "Nicholas", friends: ["Shelby", "Court", "Van"] }; var anotherPerson = object(person); anotherPerson.name = "Greg"; anotherPerson.friends.push("Rob");
19、寄生组合式继承
function object(o){ function F(){} F.prototype = o; return new F(); } function inheritPrototype(subType, superType){ var prototype = object(superType.prototype); //create object prototype.constructor = subType; //augment object subType.prototype = prototype; //assign object } function SuperType(name){ this.name = name; this.colors = ["red", "blue", "green"]; } SuperType.prototype.sayName = function(){ alert(this.name); }; function SubType(name, age){ SuperType.call(this, name); this.age = age; } inheritPrototype(SubType, SuperType); SubType.prototype.sayAge = function(){ alert(this.age); }; var instance1 = new SubType("Nicholas", 29); instance1.colors.push("black"); alert(instance1.colors); //"red,blue,green,black" instance1.sayName(); //"Nicholas"; instance1.sayAge(); //29 var instance2 = new SubType("Greg", 27); alert(instance2.colors); //"red,blue,green" instance2.sayName(); //"Greg"; instance2.sayAge(); //27
以上就是今天的javascript学习小结,之后每天还会继续更新,希望大家继续关注。