jsで継承を実装する方法

継承の目的は、別のオブジェクトのプロパティとメソッドを再利用することです。

目次

1 プロトタイプチェーンの継承

2 コンストラクターの継承

3 構成の継承 

4 プロトタイプの継承

5 寄生継承

6 寄生成分の継承


1 プロトタイプチェーンの継承

親クラスのインスタンス オブジェクトをサブクラスのプロトタイプとして使用します Student.prototype = new person()

// 父类: 公共属性和方法
function Person() {
  this.name = "why"
  this.friends = []
}

Person.prototype.eating = function() {
  console.log(this.name + " eating~")
}

// 子类: 特有属性和方法
function Student() {
  this.sno = 111
}

var p = new Person()
Student.prototype = p

Student.prototype.studying = function() {
  console.log(this.name + " studying~")
}


// name/sno
var stu = new Student()

// console.log(stu.name)
// stu.eating()

// stu.studying()


// 原型链实现继承的弊端:
// 1.第一个弊端: 打印stu对象, 继承的属性是看不到的
// console.log(stu.name)

// 2.第二个弊端: 创建出来两个stu的对象
var stu1 = new Student()
var stu2 = new Student()

// 直接修改对象上的属性, 是给本对象添加了一个新属性
stu1.name = "kobe"
console.log(stu2.name)

// 获取引用, 修改引用中的值, 会相互影响
stu1.friends.push("kobe")

console.log(stu1.friends)
console.log(stu2.friends)

// 3.第三个弊端: 在前面实现类的过程中都没有传递参数
var stu3 = new Student("lilei", 112)

2 コンストラクターの継承

// 父类: 公共属性和方法
function Person(name, age, friends) {
  // this = stu
  this.name = name
  this.age = age
  this.friends = friends
}

Person.prototype.eating = function() {
  console.log(this.name + " eating~")
}

// 子类: 特有属性和方法
function Student(name, age, friends, sno) {
  Person.call(this, name, age, friends)
  // this.name = name
  // this.age = age
  // this.friends = friends
  this.sno = 111
}

var p = new Person()
Student.prototype = p

Student.prototype.studying = function() {
  console.log(this.name + " studying~")
}


// name/sno
var stu = new Student("why", 18, ["kobe"], 111)

// console.log(stu.name)
// stu.eating()

// stu.studying()


// 原型链实现继承已经解决的弊端
// 1.第一个弊端: 打印stu对象, 继承的属性是看不到的
console.log(stu)

// 2.第二个弊端: 创建出来两个stu的对象
var stu1 = new Student("why", 18, ["lilei"], 111)
var stu2 = new Student("kobe", 30, ["james"], 112)

// // 直接修改对象上的属性, 是给本对象添加了一个新属性
// stu1.name = "kobe"
// console.log(stu2.name)

// // 获取引用, 修改引用中的值, 会相互影响
stu1.friends.push("lucy")

console.log(stu1.friends)
console.log(stu2.friends)

// // 3.第三个弊端: 在前面实现类的过程中都没有传递参数
// var stu3 = new Student("lilei", 112)

強調: コンストラクターの借用には欠点もあります。
 1.: person 関数が少なくとも 2 回呼び出されます
 。 2. stu のプロトタイプ オブジェクトにはさらにいくつかのプロパティがありますが、これらのプロパティは必要ありません。

3 構成の継承 

コンストラクターはインスタンスのプロパティを継承し、親クラスのプロトタイプをサブクラスのプロトタイプとして受け取り、プロトタイプ チェーンを使用してプロトタイプのプロパティとメソッドの継承を実現します Student.prototype = Object.create(Person.prototype)

// 父类: 公共属性和方法
function Person(name, age, friends) {
  // this = stu
  this.name = name;
  this.age = age;
  this.friends = friends;
}

Person.prototype.eating = function () {
  console.log(this.name + ' eating~');
};

// 子类: 特有属性和方法
function Student(name, age, friends, sno) {
  Person.call(this, name, age, friends);
  // this.name = name
  // this.age = age
  // this.friends = friends
  this.sno = sno;
}

// 直接将父类的原型赋值给子类, 作为子类的原型
Student.prototype = Person.prototype;

Student.prototype.studying = function () {
  console.log(this.name + ' studying~');
};

// name/sno
var stu = new Student('why', 18, ['kobe'], 111);
console.log(stu);
stu.eating();

質問

1. コンストラクターは 2 回呼び出されます。1 回目はサブタイプ プロトタイプ オブジェクトの作成時、もう 1 回はサブタイプ インスタンスの作成時です。

2. 型には属性のコピーが 2 つ存在します。1 つはプロトタイプ オブジェクトに、もう 1 つはサブクラス インスタンスにあります。

 4 プロトタイプの継承

参照型を含むプロパティ値は、プロトタイプ チェーンの継承と同様に、常に対応する値を共有します。

var obj = {
  name: "why",
  age: 18
}


//将传入的对象作为创建的对象的原型
var info = Object.create(obj)

// 原型式继承函数
function createObject1(o) {
  var newObj = {}
  Object.setPrototypeOf(newObj, o)
  return newObj
}

function createObject2(o) {
  function Fn() {}
  Fn.prototype = o
  var newObj = new Fn()
  return newObj
}

// var info = createObject2(obj)
var info = Object.create(obj)
console.log(info)
console.log(info.__proto__)

5 寄生継承

継承プロセスをカプセル化する関数を作成します。これにより、何らかの方法でオブジェクトが内部的に強化され、最終的にオブジェクトが返されます。

var personObj = {
    running: function() {
        console.log('running');
    },
};

function createStudent(name) {
    var stu = Object.create(personObj);
    stu.name = name;
    stu.studying = function() {
        console.log('studying~');
    };
    return stu;
}

var stuObj = createStudent('why');
var stuObj1 = createStudent('kobe');
var stuObj2 = createStudent('james');

6 寄生成分の継承

 

function createObject(o) {
    function Fn() {}
    Fn.prototype = o;
    return new Fn();
}

function inheritPrototype(SubType, SuperType) {
    // SubType.prototype = Object.create(SuperType.prototype);
    // 或者
    SubType.prototype = createObject(SuperType.prototype);
    Object.defineProperty(SubType.prototype, 'constructor', {
        enumerable: false,
        configurable: true,
        writable: true,
        value: SubType,
    });
}

function Person(name, age, friends) {
    this.name = name;
    this.age = age;
    this.friends = friends;
}

Person.prototype.running = function() {
    console.log('running~');
};

Person.prototype.eating = function() {
    console.log('eating~');
};

function Student(name, age, friends, sno, score) {
    // 原型式继承函数
    Person.call(this, name, age, friends);
    this.sno = sno;
    this.score = score;
}

inheritPrototype(Student, Person);

Student.prototype.studying = function() {
    console.log('studying~');
};

var stu = new Student('why', 18, ['kobe'], 111, 100);
console.log(stu);
stu.studying();
stu.running();
stu.eating();

console.log(stu.constructor.name);

おすすめ

転載: blog.csdn.net/m0_50789696/article/details/129250506
おすすめ