JS中对象继承方式

JS对象继承方式

摘自《JavaScript的对象继承方式,有几种写法》,作者:peakedness
链接:https://my.oschina.net/u/3970421/blog/2872629

方式一:对象冒充

原理:构造函数使用this关键字给所有属性和方法赋值(即采用类声明的构造函数方式)。因为构造函数只是一个函数,所以可使Parent构造函数称为Children的方法,然后调用它。Children会收到Parent的构造函数中定义的属性和方法。


//父类构造函数
var Parent = function(name){
    this.name = name;
    this.sayHi = function(){
        console.log("Hi" + this.name + ".");
    }
}

var Children = function(name){
    
    this.method = Parent;
    this.method(name);  //实现继承
    delete this.method;

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

var P = new Parent("john");
var C = new Children("joe");

P.sayHi();      //Hi john
C.sayHi();      //Hi joe
C.getName();    //joe

方式二:原型链继承

原理:JS是一门基于原型的语言。在JS中prototype对象的任何属性和方法都被传递给那个类的所有实例。

//父类构造函数
var Parent = function(name){
    this.name = name;
    this.sayHi = function(){
        console.log("Hi" + this.name + ".");
    }
}
//子类构造函数
var Children = function(){};

Children.prototype = new Parent();

var P = new Parent();
var C = new Children();

P.sayHi();
C.sayHi();

注意:
调用Parent的构造函数,没有给它传递参数。这是原型链中的标准做法,要确保构造函数没有任何参数。

方式三:使用call或apply方法

原理:通过改变this指向实现继承。apply第二个参数必须是数组,call依次传入。

//父类构造函数
var Parent = function(name){
    this.name = name;
    this.sayHi = function(){
        console.log("Hi" + this.name + ".");
    }
};
//子类构造函数
var Children = function(name){
    Parent.call(this,name);
    this.getName = function(){
        console.log(this.name);
    }
};
var C = new Children("Joe");
C.sayHi();  //Hi john
C.getName();    //Joe

方式四:混合使用(推荐)

使用原型链就无法使用带参数的构造函数了
因此,在JS中创建类,最好使用构造函数定义属性,使用原型链定义方法。

//父类构造函数
var Parent = function(name){
    this.name = name;
}
Parent.prototype.sayHi = function(){
    console.log("Hi ! " + this.name + "!!!");
}
var P = new Parent("John");
P.sayHi();  //Hi John !!!

方式五:使用Object.create方法

Object.create方法会使用指定的原型对象及其属性去创建一个新的对象

//父类构造函数
var Parent = function(name){
    this.name = name;
}
Parent.prototype.sayHi = function(){
    console.log("Hi " + this.name + ".");
}
//子类构造函数
var Children = function(name,age){
    this.age = age;
    Parent.call(this,name);     //属性不在prototype上
};

Children.prototype = Object.create(Parent.prototype);
Children.prototype.constructor = Children;
Children.prototype.getAge = function(){
    console.log(this.age);
};

var P = new Parent("John");
var C = new Children("Joe",30);

P.sayHi();  //Hi John
C.sayHi();  //Hi Joe
C.getAge(); //30

注意:
当执行Children.prototype = Object.create(Parent.prototype)这个语句后,Children的constructor就被变为Parent,因此需要将Children.protype.constructor重新指定为Children本身。

constructor指向创建此对象的函数的引用。

方式六:extends关键字实现继承

class Paren{
    constructor(name,age){
        this.name = name;
        this.age = age;
    }
}
class Children extends Parent{
    constructor(name,age,job){
        super(name,age);    //super必须在前,否则代码报错
        this.job = job;
    }
}

注意:
子类的constructor方法没有调用super之前,就使用this关键字会报错。原因是:子类Children的构造函数之中的super(),代表调用父类Parent的构造函数。

super虽然代表了父类Parent的构造函数,但是返回的是子类Children的实例,即super内部的this指的是Children,因此super()在这里相当于Parent.prototype.constructor.call(this);

posted @ 2018-11-12 22:31  南华秋水  阅读(6020)  评论(0编辑  收藏  举报