继承

136 阅读4分钟

es6 class的继承

基本的继承

class Point {
  constructor(x, y) {
    this.x = x;
    this.y = y;
  }
  getposition () {
    console.log("x:" + this.x, "y:" + this.y)
  }
}
class ColorPoint extends Point {
  constructor(x, y, color) {
    super(x, y);   //子类调用父类的构造函数 继承父类的属性 
    this.color = color; //子类自己的属性必须写在super函数之后,不然找不到this
  }
}

var colorpoint = new ColorPoint(1, 2, "red");
colorpoint.getposition() // x:1 y:2
console.log(colorpoint.color) //red

静态方法和静态属性

(1)静态方法和静态属性不能被实例访问,只能被类访问,同时类也不能访问实例方法和实例方法。

(2)静态方法和静态属性的写法:

class Point {
 constructor(x, y) {
   this.x = x;  // 实例属性
   this.y = y;
 }
 z = 10; //实例属性
 getposition () {  //实例方法 保存在prototype中
   console.log("x:" + this.x, "y:" + this.y)
 }
 static pointname = "biubiu" //静态属性
 static getname () {  //静态方法 之能访问静态属性
   console.log(this.pointname)
   console.log(this.otherpointname)
 }
}
Point.otherpointname = "piupiu";  //也是静态属性,是另一种写法,但是没有封装在类里面
class ColorPoint extends Point {
 constructor(x, y, color) {
   super(x, y);   //子类调用父类的构造函数 继承父类的属性
   this.color = color; //子类自己的属性
 }
}
var colorpoint = new ColorPoint(1, 2, "red");
colorpoint.getposition() // x:1 y:2
console.log(colorpoint.color)
Point.getname() // biubiu  piupiu
ColorPoint.getname()// biubiu  piupiu  子类继承了父类的静态属性和方法 
colorpoint.getname() //typeerror 子类的实例不能调用父类的静态方法

es5和es6继承的区别

es5继承是先创造子类的实例对象this,然后再将父类的方法添加到this上面(Parent.call(this));

es6继承是先创造父类的实例对象this(所以必须先调用super方法),然后在子类的构造函数修改this。

这一区别使es5不能继承原生构造函数。因为原生构造函数的内部属性是不能获取的,通过apply()或者分配给原型对象都不行。

原生构造函数包括:Number(),String(),Array(),Boolean(),Date(),Function(),RegExp(),Error(),Object()9个。

  • super关键字

    super关键字可以当做函数使用,也可以当作对象使用。

    第一种情况,super作为函数调用时代表父类的构造函数。而且只能用在子类的构造函数中,在普通函 数中不能调用。虽然是调用了父类的构造函数,但是返回的是子类的实例,即super内部的this指向的 是子类。

    第二种情况,super作为对象时在普通方法中指向父类的原型对象,在静态方法中指向父类。即在子类的普通实例方法中指向普通实例方法,在静态方法中指向静态方法。

父类的实例方法和属性调用不到,只能调用原型的方法和属性。

super调用父类的方法时会绑定this,即this跟随上下文。

类的prototype属性和_proto_属性

class作为作为构造函数的语法糖,同时有以上两个属性:

(1)子类的_proto_属性表示构造函数的继承,指向父类;

(2)子类的prototype属性的_proto_属性表示方法的继承,指向父类的protype属性。

JS高级程序设计里面的继承

寄生组合式继承 最合理和常用

function Person (name) {
  this.name = name;
}
Person.prototype.sayName = function () {
  console.log(this.name)
}
function Student (name, age) {
  Person.call(this, name) //调用父类的构造函数 这样子类也有一个name实例属性了
  this.age = age;
}

Student.prototype = Object.create(Person.prototype) //子类的原型指向父类的原型,不用调用两次构造函数
Student.prototype.constructor = Student;

Student.prototype.sayAge = function () {
  console.log(this.age)
}

var son = new Student("bibi", 12)
son.sayName()
son.sayAge()

寄生组合式继承和组合式继承的区别

组合继承 Students.prototype = new Person() 这样调用一次构造函数,Person的实例方法出现在Students的原型中,var student = new Student()时又调用一次Person的构造函数,这个时候Person的实例属性变成Students的实例属性,覆盖了原型中的属性,浪费了空间,没必要。

原型链继承 子类的原型等于父类的实例

function Person (name) {
  this.name = "bibi";
  this.friend = ["biubiu", "piupiu"]
}
Person.prototype.sayName = function () {
  console.log(this.name)
}
function Student (name, age) {
  this.age = age;
}
Student.prototype.sayAge = function () {
  console.log(this.age)
}
// 原型链继承  
//问题:(1)Person的实例属性成为student的原型属性,那么所有实例对象会共享引用类型的原型属性
// (2)没办法在不影响所有实例对象的情况下向父类传参
Student.prototype = new Person()

var son = new Student()
var son2 = new Student()
son.friend.push("Anny");
console.log(son2.friend) //[ 'biubiu', 'piupiu', 'Anny' ]

借用构造函数 子类的构造函数调用父类的构造函数


function Person () {
  this.name = "bibi";
  this.friend = ["biubiu", "piupiu"]
}
Person.prototype.sayName = function () {
  console.log(this.name)
}
function Student (age) {
  Person.call(this)    //借用构造函数方法,问题:不能调用父类的原型方法
  this.age = age;
}
Student.prototype.sayAge = function () {
  console.log(this.age)
}

var son = new Student()
var son2 = new Student()
son.friend.push("Anny");
console.log(son2.friend)
son.sayName() //报错sayName不是一个方法

原型式继承

var person = {
  name: "gred",
  friend: ["bob", "alice"]
}
var student = Object.create(person) //让子类的原型等于已有对象的实例,缺点也是原型属性共享
student.age = 12

寄生式继承

function creatOtherPerson () {
  var clone = Object.create(Person) 
  clone.sayHi = function () {
    console.log("Hi")
  }
  return clone
}
var anotherperson = creatOtherPerson()
anotherperson.sayHi() // Hi