理解javascript 继承与类

181 阅读2分钟

在一些框架使用中经常会遇到一些诸如class,extends, super,constructor 等关键字或方法,这些都的原理与实现是怎样的呢

  • ES5 继承方法
  • ES6 的类
  • ES6 类的继承
  • 模拟类的现

ES5 继承方法

原型链继承

function Parent(){
   this.name = 'Nick'
}
Parent.prototype.getName = function(){
    console.log(this.name);
} 
function Child (){
}

Child.prototype = new Parent()

var child1 = new Child()

console.log(child1.getName()) //Nick

问题(1)包含引用类型值的原型属性会被所有实例共享 (2)创建子类型Child实例时无法传递参数给Parent

借用构造函数继承(在子类构造函数内部调用超类型构造函数【经典继承】

1.避免了引用类型属性被所有实例共享

funcion Parent(){
    this.colors = ['red','blue','green']
}
function Child(){
    Parent.call(this)
}
var child1 = new Child()
child1.colors.push('black')
child1.colors //'red','blue','green' ,'black'

var child2 = new Child()
child2.colors //'red','blue','green' 

2.可以传递参数

funcion Parent(name){
   this.name = name
}
function Child(name){
   Parent.call(name)
}
var child1 = new Child('kevin');

console.log(child1.name); // kevin

var child2 = new Child('daisy');

console.log(child2.name); // daisy

问题:方法都在构造函数中定义,每次创建实例都会创建一遍方法

组合继承(经典继承+构造函数)

function Parent (name){
    this.name = name 
    this.colors = ['red','blue','green'];
}
Parent.prototype.getName = function (){
    console.log(this.name)
}
function Child (name,age){
    Parent.call(this,name)
    this.age = age
}

Child.prototype = new Parent()

Child.prototype.getAge = function (){
    console.log(this.age)
}
var child1 = new Child('nick',12)
child1.colors.push('black');
console.log(child1.colors);
child1.getName();
child1.getAge();child1;

融合原型链继承和构造函数的优点,是 JavaScript 中最常用的继承模式。

问题 会调用两次父构造函数 (1) Parent.call(this,name)(2)Child.prototype = new Parent()

原型式继承

先创建一个临时性构造函数。然后将传入的对象作为这个构造函数的原型,最后返回这个临时类型的新实例

function object(o){
    function F(){}
    F.prototype = o
    return new F()
}
// 用此方法得到的新对象其属性通过hasOwnProperty方法可看到是存在新对象的原型上的而不是在新创建的对象上

var person = {
    name:'Nich',
    friends:['tysd','dfsd','3432']
}
var person1 = object(person);
person1.name = 'Gert';
person1.friends.push('Ron');

var person2 = object(person)
person2.name = 'Linad'
person2.friends.push('Ioios');

问题:包含引用类型的属性值会被共享

寄生式继承

创建一个仅用于封装继承过程的函数,该函数在内部以某种形式来做增强对象,最后返回对象。

function createObj (o) {
    var clone = Object.create(o);
    clone.sayName = function () {
        console.log('hi');
    }
    return clone;
}

跟借用构造函数模式一样,每次创建对象都会创建一遍方法。

寄生组合式继承

组合继承的问题在于会调用两次父构造函数

function Parent (name) {
    this.name = name;
    this.colors = ['red', 'blue', 'green'];
}

Parent.prototype.getName = function () {
    console.log(this.name)
}

function Child (name, age) {
    Parent.call(this, name);
    this.age = age;
}

// 关键的三步
var F = function () {};

F.prototype = Parent.prototype;

Child.prototype = new F();


var child1 = new Child('kevin', '18');

console.log(child1);


即:
function object(o) {
    function F() {}
    F.prototype = o;
    return new F();
}

function prototype(child, parent) {
    var prototype = object(parent.prototype);
    prototype.constructor = child;
    child.prototype = prototype;
}