1. Javascriptの継承
継承する1.1プロトタイプチェーン
function Parent() {
this.name = 'zhangsan';
this.children = ['A', 'B', 'C'];
}
Parent.prototype.getName = function() {
console.log(this.name);
}
function Child() {
}
Child.prototype = new Parent();
var child = new Child();
console.log(child.getName());
[!注]
主な問題:
- 参照型は、属性(this.children.push(「名前」))のすべてのインスタンスで共有されています
- 子供のインスタンスを作成するとき、私たちは親にパラメータを渡すことはできません
1.2ボローコンストラクタ(古典的な継承)
function Parent(age) {
this.names = ['zhangsan', 'lisi'];
this.age = age;
this.getName = function() {
return this.names;
}
this.getAge = function() {
return this.age;
}
}
function Child(age) {
Parent.call(this, age);
}
var child = new Child(18);
child.names.push('haha');
console.log(child.names);
var child2 = new Child(20);
child2.names.push('yaya');
console.log(child2.names);
[!注]
利点:
- プロパティの参照タイプを回避するすべてのインスタンスによって共有されています
- リファレンスは、直接的には親子に送信することができます
[!危険]
短所:
- メソッドがコンストラクタで定義され、各インスタンスは、メソッドを作成し、再び作成されます
継承1.3組み合わせ(継承と連続古典2のアプローチのプロトタイプチェーン)
/**
* 父类构造函数
* @param name
* @constructor
*/
function Parent(name) {
this.name = name;
this.colors = ['red', 'green', 'blue'];
}
Parent.prototype.getName = function() {
console.log(this.name);
}
// child
function Child(name, age) {
Parent.call(this, name);
this.age = age;
}
Child.prototype = new Parent();
// 校正child的构造函数
Child.prototype.constructor = Child;
// 创建实例
var child1 = new Child('zhangsan', 18);
child1.colors.push('orange');
console.log(child1.name, child1.age, child1.colors); // zhangsan 18 (4) ["red", "green", "blue", "orange"]
var child2 = new Child('lisi', 28);
console.log(child2.name, child2.age, child2.colors); // lisi 28 (3) ["red", "green", "blue"]
[NOTE!]
利点:プロトタイプ継承チェーンとコンストラクタの利点を組み合わせ、Javascriptが相続の最も一般的に使用されるモードです
要約の長所と短所を継承した方法の2 A品種
2.1原型継承
function createObj(o) {
function F(){};
// 关键:将传入的对象作为创建对象的原型
F.prototype = o;
return new F();
}
// test
var person = {
name: 'zhangsan',
friends: ['lisi', 'wangwu']
}
var person1 = createObj(person);
var person2 = createObj(person);
person1.name = 'wangdachui';
console.log(person1.name, person2.name); // wangdachui, zhangsan
person1.friends.push('songxiaobao');
console.log(person2.friends); // lisi wangwu songxiaobao
[!危険]
短所:
- 参照型のプロパティ値のために常に対応する値、およびそれを継承するプロトタイプチェーンを共有しています
2.2寄生継承
// 创建一个用于封装继承过程的函数,这个函数在内部以某种形式来增强对象
function createObj(o) {
var clone = Object.create(o);
clone.sayName = function() {
console.log('say HelloWorld');
}
return clone;
}
【危険!]
短所:オブジェクトを作成ボローコンストラクタとパターンは、方法再びたびに作成され
2.3継承寄生合成
2.3.1基本的なバージョン
function Parent(name) {
this.name = name;
this.colors = ['red', 'green', 'blue'];
}
Parent.prototype.getName = function() {
console.log(this, name);
}
function Child(name, age) {
Parent.call(this, name);
this.age = age;
}
// test1:
// 1. 设置子类实例的时候会调用父类的构造函数
Child.prototype = new Parent();
// 2. 创建子类实例的时候也会调用父类的构造函数
var child1 = new Child('zhangsan', 18); // Parent.call(this, name);
// 思考:如何减少父类构造函数的调用次数呢?
var F = function(){};
F.prototype = Parent.prototype;
Child.prototype = new F();
// 思考:下面的这一句话可以吗?
/* 分析:因为此时Child.prototype和Parent.prototype此时指向的是同一个对象,
因此部分数据相当于此时是共享的(引用)。
比如此时增加 Child.prototype.testProp = 1;
同时会影响 Parent.prototype 的属性的。
如果不模拟,直接上 es5 的话应该是下面这样吧
Child.prototype = Object.create(Parent.prototype);*/
Child.prototype = Parent.prototype;
// 上面的三句话可以简化为下面的一句话
Child.prototype = Object.create(Parent.prototype);
// test2:
var child2 = new Child('lisi', 24);
最適化されたバージョン2.3.2
// 自封装一个继承的方法
function object(o) {
// 下面的三句话实际上就是类似于:var o = Object.create(o.prototype)
function F(){};
F.prototype = o.prototype;
return new F();
}
function prototype(child, parent) {
var prototype = object(parent.prototype);
// 维护原型对象prototype里面的constructor属性
prototype.constructor = child;
child.prototype = prototype;
}
// 调用的时候
prototype(Child, Parent)
3.オブジェクトを作成する方法JS
- リテラルの作成
- コンストラクタを作成します
- Object.create()
var o1 = {name: 'value'};
var o2 = new Object({name: 'value'});
var M = function() {this.name = 'o3'};
var o3 = new M();
var P = {name: 'o4'};
var o4 = Object.create(P)
4.プロトタイプとプロトタイプチェーン
4.1プロトタイプ
- すべてのオブジェクトはJavaScriptに含まれている
__proto__
内部属性、対応するには、オブジェクトのプロトタイプであります - JavaScriptの関数オブジェクト、プロトタイプに加えて
__proto__
、だけでなく、事前にprototypeプロパティ - 関数は、オブジェクトのプロトタイプの例として、プロトタイプのプロパティ値であり、コンストラクタ、などのオブジェクトのインスタンスを作成するとき
__proto__
。
4.2プロトタイプチェーン
任意の目的は、上記のプロトタイプ・オブジェクト・インスタンスとインスタンスメソッドが共有され、プロトタイプチェーンにより求め、その対応するプロトタイプ・オブジェクトのインスタンスであることができます。
オブジェクトは、メソッドやプロパティを検索するとき、彼は最初に見つけたとき、彼はプロトタイプチェーンアップターンの外観になります、自分自身のオブジェクトに移動します。
[NOTE!]
注:関数はオブジェクト関数のインスタンスであるため、唯一の関数プロトタイプ、オブジェクトのインスタンスが唯一のいくつかの__proto__機能ながら、__proto__を持っているが
原則instanceofは4.3
[!NOTE]
__proto__属性コンストラクタインスタンスオブジェクトが参照して決定されていないプロトタイプ。ない場合は、彼がトップオブジェクトまで__proto__オブジェクトに沿って検索します。
4.4は、直接ターゲットクラスのどのインスタンスが決定されます
[!NOTE]は
使用对象.construcor
を直接測定することができます
新しい何が起こるか4.5コンストラクタ、?
var obj = {};
obj.__proto__ = Base.prototype;
Base.call(obj);
- 新しいオブジェクトobjを作成します。
- メンバオブジェクトプロトタイプ関数にこの空のオブジェクト点の__proto__メンバーは、ベースオブジェクト
- ベースこのポインタはBase.call(OBJ)の実装と同等の機能オブジェクトobjを置き換えます。
- コンストラクタが表示されたオブジェクトを返す場合、そのオブジェクトは、このために、この例で返されます。それ以外の場合は、新しく作成されたオブジェクトを返します。
4.6クラス
// 普通写法
function Animal() {
this.name = 'name'
}
// ES6
class Animal2 {
constructor () {
this.name = 'name';
}
}