类和对象

2018-03-03大约7分钟

JavaScript是一个基于对象的语言,连函数都是对象,因此创建对象是很简单的,简单到用{}就能创建一个对象出来,并且可以动态为其添加属性和方法。

不过,这种方式创建出来的对象实例是无法再派生出新的对象,也无法让其他对象来继承,在本章就介绍一下如何创建可以继承的类对象。

基于function创建类

在ES6之前的JavaScript中,是没有像其他语言一样的class关键字的,因此无法很直观地定义一个类出来,不过可以通过function来定义一个类对象,然后结合new关键字一起创建出新的对象。

定义类

通过函数来创建一个类可能是最常见的一种方法了。你可以定义一个JavaScript函数,然后用new关键字来创建一个对象。

function Dog(type, color) {       // 定义一个函数作为类。类名按照编码规范,以大写字母开头
    this.type = type;                   // 用this关键字来创建和初始化类的属性
    this.color = color;
}

Dog.prototype.getInfo = function () {     // 在Dog的prototype属性上添加对象的方法,可以用this访问类的其它属性
    return `${this.color}${this.type}狗`;
};

const dog = new Dog("牧羊犬", "白色");   // 用new关键字创建新对象
console.log(dog.getInfo());                       // 可以直接调用新创建出对象的方法

dog.color = "红色";                                   // 修改对象的属性
console.log(dog.getInfo());                       // 可以看到对象的属性被修改了

需要注意的是,定义类的方法,不能直接定义在构造函数里面,而是要定义到函数的prototype的属性上面。比如这样做:

function Dog(type, color) {
    this.type = type; 
    this.color = color;
    this.getInfo = function () {
        return `${this.color}${this.type}狗`;
    };
}

const dog = new Dog("牧羊犬", "白色"); 
console.log(dog.getInfo()); 

缺点就是每次通过new创建出一个新的对象,就需要为这个新的对象创建一个方法,不够高效。如果是在prototype上的话,所有new出来的Dog类型的对象,都共用Dog类对象的prototype上的方法了。

继承

JavaScript对象是一种独特的基于原型(prototype)的继承方式。

/*
定义Dog作为父类
*/
function Dog(type, color) {
    this.type = type;
    this.color = color;
}

Dog.prototype.getInfo = function () {
    return `${this.color}${this.type}狗`;
};

/*
定义子类
*/

function ShepherdDog(color, weight) {
    this.weight = weight;
    Dog.call(this, "牧羊犬", color); // 调用父类的构造函数
}

// 子类继承父类
ShepherdDog.prototype = Object.create(Dog.prototype);   

// 改变ShepherdDog.prototype指向新的对象后,要重新设置构造函数为自身
ShepherdDog.prototype.constructor = ShepherdDog;                

/*
使用子类
*/
const dog = new ShepherdDog("白色", 10);    // 创建子类
console.log(dog.getInfo());

是不是感觉有点晕了? 其实没关系,现在技术发展的趋势是用ES6,因此除非特殊情况需要用prototype来继承,大多数情况,我们完全可以用class关键字来让代码变得更容易写。