类的声明
使用构造函数声明
function Animal(name){
this.name = name;
}
使用 class
声明类
class Animal {
constructor(name) {
this.name = name;
}
}
类的实例化
使用 new
操作符来实例化一个类
const animal = new Animal('dog');
类的继承
借助构造函数实现继承
function Animal(name){
this.name = name;
}
Animal.prototype.say = function() {
console.log("I'm Animal");
};
function Dog() {
Animal.call(this);
this.eyes = 2;
}
console.log(new Dog().say()); // 报错
缺点:通过这种方式实现的继承是部分继承,只能继承构造函数中的内容,不能继承父类原型链上的属性。
借助原型链实现继承
function Animal(name){
this.name = name;
this.numbers = [1, 2, 3];
}
Animal.prototype.say = function() {
console.log("I'm Animal");
};
function Dog() {
this.eyes = 2;
}
Dog.prototype = new Animal();
缺点:如果通过 Dog
实例化两个对象,当其中一个对象对原型中的数据发生修改时,因为两个实例拥有同一个原型,所以第二个实例也会发生对应的变化。
const dog1 = new Dog();
const dog2 = new Dog();
dog1.numbers.push(4); // [1, 2, 3, 4]
console.log(dog2.numbers); // [1, 2, 3, 4]
组合方式
function Animal(name){
this.name = name;
this.numbers = [1, 2, 3];
}
Animal.prototype.say = function() {
console.log("I'm Animal");
};
function Dog() {
Animal.call(this);
this.eyes = 2;
}
Dog.prototype = new Animal();
const dog1 = new Dog();
const dog2 = new Dog();
dog1.numbers.push(4); // [1, 2, 3, 4]
console.log(dog2.numbers); // [1, 2, 3]
缺点:父类声明了两次
组合方式优化
function Animal(name){
this.name = name;
this.numbers = [1, 2, 3];
}
Animal.prototype.say = function() {
console.log("I'm Animal");
};
function Dog() {
Animal.call(this);
this.eyes = 2;
}
Dog.prototype = Animal.prototype;
const dog1 = new Dog();
const dog2 = new Dog();
dog1.numbers.push(4); // [1, 2, 3, 4]
console.log(dog2.numbers); // [1, 2, 3]
缺点:实例对象的 constructor
指向父类而不是指向构造函数
组合方式2
function Animal(name){
this.name = name;
this.numbers = [1, 2, 3];
}
Animal.prototype.say = function() {
console.log("I'm Animal");
};
function Dog() {
Animal.call(this);
this.eyes = 2;
}
Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;
const dog1 = new Dog();
const dog2 = new Dog();
dog1.numbers.push(4); // [1, 2, 3, 4]
console.log(dog2.numbers); // [1, 2, 3]