How to implement inheritance in js

The purpose of inheritance is to reuse the properties and methods of another object.

Table of contents

1 Prototype chain inheritance

2 Constructor inheritance

3 Composition inheritance 

4 Prototypal inheritance

5 Parasitic inheritance

6 Parasitic compositional inheritance


1 Prototype chain inheritance

Use the instance object of the parent class as the prototype of the subclass 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 Constructor inheritance

// 父类: 公共属性和方法
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)

Emphasis: Borrowing the constructor also has disadvantages:
 1.: The Person function is called at least twice
 2. There will be some more properties on the prototype object of stu, but these properties are not necessary

3 Composition inheritance 

The constructor inherits the instance properties, takes the prototype of the parent class as the prototype of the subclass, and uses the prototype chain to realize the inheritance of prototype properties and methods 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();

question

1. The constructor will be called twice: once when creating the subtype prototype object, and once when creating the subtype instance.

2. There will be two copies of the attributes in the type: one in the prototype object and one in the subclass instance.

 4 Prototypal inheritance

Property values ​​that contain reference types always share corresponding values, just like prototype chain inheritance

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 Parasitic inheritance

Create a function that encapsulates the inheritance process, which internally enhances the object in some way, and finally returns the object;

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 Parasitic compositional inheritance

 

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);

Guess you like

Origin blog.csdn.net/m0_50789696/article/details/129250506