js继承

112 阅读2分钟

js继承

一,原型继承

// 父
function Person(){
    this.type = '人类';
    this.info = {time:5000}
}
Person.prototype.say = function(){
    console.log('说话。。');
}
// 子
function Man(){

}
// 原型继承:让子的原型指向父的一个实例对象
Man.prototype = new Person();

var m = new Man();
console.log(m.type); //人类
m.say(); //说话。。
// 缺点
var m2 = new Man();
m2.info.time = 1000;
console.log(m.info.time); //1000

原型继承的缺点:

  • 父类的引用类型属性会被所有子类实例共享,任何一个子类实例修改了父类的引用类型属性,其他子类实例都会受到影响
  • 创建子类实例的时候,不能向父类传参

二,ES6的继承方法-class

  1. Es6新数据类型class, 用来创建对象
  2. constructor 构造器, 当调用new Person(), 构造器里的方法就会运行
class Person2{
    // 构造器(其实就是es5里的构造函数)
    constructor(nation){
        this.nation = nation;
    }
    // 原型上的方法直接写就行
    say(){
        console.log(`这是一个${this.nation}人`);
    }
    // Person2自身上的方法-加上static
    static sing(){
        console.log('人类会唱歌');
    }
}
// 实现继承
class Man2 extends Person2{
    constructor(nation){
        super(nation); //调用父类的构造函数
    }
}
var m1 = new Man2('中国')
console.log(m1.nation); //中国
m1.say() //这是一个中国人

三,其他继承模式

1.借用构造函数继承

function Father(name) {
    this.name = name;
    this.info = {time:10};
    this.say = function () {
        console.log("hello");
    };
}

function Child(name) {
    // 调用Father方法-重点
    Father.call(this, name);
}
var c = new Child('hhh')
console.log(c.name); //hhh
c.say() //hello
// 测试
var c2 = new Child('www')
c2.info.time = 0;
console.log(c.info.time); //10

优点

  1. 避免了引用类型属性被所有实例共享
  2. 可以向父类传参 缺点
  3. 父类原型上的东西无法继承
  4. 每次new子类都要调用父类

2.组合继承(原型继承和借用构造函数继承的组合)

function Father2(name, age) {
	this.name = name;
	this.age = age;
}
Father2.prototype.say = function() {
	console.log('hello');
}

function Child2(name,age) {
	Father2.call(this,name,age);
}
Child2.prototype = new Father2();

var child = new Child2('Tom', 22);
console.log(child);  //Father2 { name: 'Tom', age: 22 }
child.say() //hello

优点

  1. 避免了引用类型属性被所有实例共享
  2. 可以向父类传参
  3. 也可以继承父类原型上的东西了 缺点
  4. 每次new子类都要调用父类

3.寄生式继承

就是创建一个封装的函数来增强原有对象的属性,跟借用构造函数一样,每个实例都会创建一遍方法

function createObj(o) {
    // Object.create() 方法创建一个拥有指定原型和若干个指定属性的对象。
	var clone = Object.create(o);
	clone.sayName = function () {
		console.log('hello');
	}
	return clone;
}

var father = {
  name: '人',
  nation: '中国',
  sing:function(){
      console.log('唱歌。。。');
  }
}

var son = createObj(father);
// son继承了father,拥有father的属性,同时还拥有sayName的方法
console.log(son.nation + son.name); //中国人
son.sayName() //hello
son.sing() //唱歌。。。

4.寄生组合式继承

es5最完美的继承方式: 原型+借用构造函数+寄生

// 原型+借用构造函数+寄生
function Person3(){
    this.type = '人类';
}
Person3.prototype.say = function(){
    console.log('说话。。。');
}

function Man3(){
    // 借用构造函数
    Person3.call(this);
}
// 原型继承 + 寄生
Man3.prototype = Object.create(Person3.prototype);//这样就可以减少组合继承中多进行一次构造函数的调用
// 寄生 Man.prototype.__proto__ === Person.prototype;
Man.prototype.constructor = Man;

var man = new Man3();
console.log(man.type); //人类
man.say() //说话。。。