基本的なスキルの前端(VII):継承(プロトタイプ、プロトタイプチェーン、実装の継承)JavaScriptで

1. JS継承メカニズム

javascirpt「サブクラス」と「親」の概念は、「クラス」(クラス)との「インスタンス」(インスタンス)、非常に独特の「プロトタイプチェーン」のおかげで(プロトタイプチェーン)モードの区別はありません実装の継承。継承は、そのコピー操作を意味しますが、デフォルトのJavaScriptオブジェクトのプロパティをコピーしません一つのオブジェクトが別のオブジェクトの委員会を通じて特性や機能にアクセスできるようにし、逆に、JavaScriptはちょうど2つのオブジェクト間の関連付けを作成し、そのので、文によって委託と呼ばれる継承は、より正確になります。

2.プロトタイプ、プロトタイプチェーンとは何ですか

1.プロトタイプ、__ __プロト、コンストラクタを区別
  1. プロトタイプ:これはJavaScriptですべての機能は、このプロパティを持っていないprototypeプロパティ、通常のオブジェクトを持つことになります属性です。コンストラクタのプロトタイププロパティの属性値が作成され、コンストラクタインスタンスのプロトタイプです。
  2. __proto__:(ヌルを除く)すべてのJavaScriptオブジェクトは、__proto__というプロパティがあり、このプロパティは、オブジェクトのプロトタイプを指します。
  3. コンストラクタ:各プロトタイプは持っているconstructor関連するコンストラクタを指してプロパティを。
function Person() {

}
var person = new Person();
console.log(person.__proto__ === Person.prototype); //true;

function Person() {

}
var person = new Person();
console.log(Person === Person.prototype.constructor); //true
//其实 person 中并没有constructor 属性,当不能读取到constructor属性时,会从 person 的原型也就是 Person.prototype中读取,正好原型中有该属性
console.log(person.constructor === Person); // true
复制代码
2.プロトタイプチェーン

JavaScriptのは、すべてのオブジェクトは、そのプロトタイプからオブジェクトに継承されます。プロトタイプオブジェクト自体が目標である、それはまた、独自のプロトタイプオブジェクトを有し、そのような層は、プロトタイプチェーン(プロトタイプ鎖)で同様のリスト構造を形成するために、トレース。オブジェクトは、JavaScriptのオブジェクト()の構成を前提としますので、すべてのエンドポイントは、オブジェクトのプロトタイププロトタイプチェーンプロパティ関数でした。プロトタイプオブジェクトObjec.prototypeもプロトタイプを指摘しているが、その原型は、ヌルnullで、プロトタイプがありません。

3. JSの実装の継承

  1. プロトタイプチェーンの継承:サブクラスのプロトタイプオブジェクトとして機能するように、親クラスのインスタンスを取ります
function Super(){
    this.val = 1;
    this.arr = [1];
}
function Sub(){
    // ...
}
Sub.prototype = new Super();    // 核心

var sub1 = new Sub();
var sub2 = new Sub();
sub1.val = 2;
sub1.arr.push(2);
alert(sub1.val);    // 2
alert(sub2.val);    // 1

alert(sub1.arr);    // 1, 2
alert(sub2.arr);    // 1, 2
// 优点: 简单,易于实现
// 缺点: 1. 修改sub1.arr后sub2.arr也变了,因为来自原型对象的引用属性是所有实例共享的。 2. 创建子类实例时,无法向父类构造函数传参
复制代码
  1. 継承ボローコンストラクタ:親クラスのコンストラクタサブクラスのインスタンスによって増強され、そのため親クラス・インスタンスは、嵌合サブクラスの複製されたインスタンスに属性した(何のプロトタイプを使用しません)
function Super(val){
    this.val = val;
    this.arr = [1];

    this.fun = function(){
        // ...
    }
}
function Sub(val){
    Super.call(this, val);   // 核心
    // ...
}

var sub1 = new Sub(1);
var sub2 = new Sub(2);
sub1.arr.push(2);
alert(sub1.val);    // 1
alert(sub2.val);    // 2

alert(sub1.arr);    // 1, 2
alert(sub2.arr);    // 1

alert(sub1.fun === sub2.fun);   // false
// 优点: 1. 解决了子类实例共享父类引用属性的问题 2. 创建子类实例时,可以向父类构造函数传参 
// 缺点: 无法实现函数复用,每个子类实例都持有一个新的fun函数,太多了就会影响性能,内存爆炸。。
复制代码
  1. 機能の再利用を実現するためにプロトタイプオブジェクトの機能の例として、:継承された(共通)の組み合わせ。また、コンストラクタメソッドを借りるの利点を維持しながら。
// 通过Super.call(this);继承父类的基本属性和引用属性并保留能传参的优点;通过Sub.prototype = new Super();继承父类函数,实现函数复用
function Super(){
    // 只在此处声明基本属性和引用属性
    this.val = 1;
    this.arr = [1];
}
//  在此处声明函数
Super.prototype.fun1 = function(){};
Super.prototype.fun2 = function(){};
//Super.prototype.fun3...
function Sub(){
    Super.call(this);   // 核心
    // ...
}
Sub.prototype = new Super();    // 核心

var sub1 = new Sub(1);
var sub2 = new Sub(2);
alert(sub1.fun === sub2.fun);   // true
// 优点: 1. 不存在引用属性共享问题 2. 可传参 3. 函数可复用
// 缺点:(一点小瑕疵)子类原型上有一份多余的父类实例属性,因为父类构造函数被调用了两次,生成了两份,而子类实例上的那一份屏蔽了子类原型上的。。。又是内存浪费,比刚才情况好点,不过确实是瑕疵
复制代码
  1. 継承寄生組成物(ベストモード):冗長親クラスインスタンス属性がプロトタイプオブジェクトを共有して切断。
function beget(obj){   // 生孩子函数 beget:龙beget龙,凤beget凤。
    var F = function(){};
    F.prototype = obj;
    return new F();
}
function Super(){
    // 只在此处声明基本属性和引用属性
    this.val = 1;
    this.arr = [1];
}
//  在此处声明函数
Super.prototype.fun1 = function(){};
Super.prototype.fun2 = function(){};
//Super.prototype.fun3...
function Sub(){
    Super.call(this);   // 核心
    // ...
}
// 用beget(Super.prototype);切掉了原型对象上多余的那份父类实例属性
var proto = beget(Super.prototype); // 核心
proto.constructor = Sub;            // 核心
Sub.prototype = proto;              // 核心

var sub = new Sub();
alert(sub.val);
alert(sub.arr);
复制代码
  1. プロトタイプ式:(なしインスタンスの属性が存在しないため、「純粋」)、それによって子供たち「純粋な」新しいオブジェクトの機能を与え、その後、徐々に増加して(インスタンスの属性を記入)へ
function beget(obj){   // 生孩子函数 beget:龙beget龙,凤beget凤。
    var F = function(){};
    F.prototype = obj;
    return new F();
}
function Super(){
    this.val = 1;
    this.arr = [1];
}

// 拿到父类对象
var sup = new Super();
// 生孩子
var sub = beget(sup);   // 核心
// 增强
sub.attr1 = 1;
sub.attr2 = 2;
//sub.attr3...

alert(sub.val);     // 1
alert(sub.arr);     // 1
alert(sub.attr1);   // 1
//ES5提供了Object.create()函数,内部就是原型式继承,IE9+支持
// 优点:从已有对象衍生新对象,不需要创建自定义类型(更像是对象复制,而不是继承。。
// 缺点: 1. 原型引用属性会被所有实例共享,因为是用整个父类对象来充当了子类原型对象,所以这个缺陷无可避免 2. 无法实现代码复用(新对象是现取的,属性是现添的,都没用函数封装,怎么复用)
复制代码
  1. 寄生:唯一のベストを着用して継承するプロトタイプ式、新しいオブジェクトを作成 - >強化 - >オブジェクトを返しますが、このプロセスは、寄生継承と呼ばれ、新しいオブジェクトが作成されるかは重要ではありません。
// 有缺陷的寄生式继承 + 不完美的组合继承 = 完美的寄生组合式继承
function beget(obj){   // 生孩子函数 beget:龙beget龙,凤beget凤。
    var F = function(){};
    F.prototype = obj;
    return new F();
}
function Super(){
    this.val = 1;
    this.arr = [1];
}
function getSubObject(obj){
    // 创建新对象
    var clone = beget(obj); // 核心
    // 增强
    clone.attr1 = 1;
    clone.attr2 = 2;
    //clone.attr3...

    return clone;
}

var sub = getSubObject(new Super());
alert(sub.val);     // 1
alert(sub.arr);     // 1
alert(sub.attr1);   // 1
// 优点: 还是不需要创建自定义类型
// 缺点: 无法实现函数复用(没用到原型,当然不行)
复制代码

ます。https://juejin.im/post/5d08cc95f265da1bb31c3af3で再現

おすすめ

転載: blog.csdn.net/weixin_34054866/article/details/93170446