js类的创建和继承

要想了解js类的创建和继承,我们要先掌握js原型与原型链。
1. 简单介绍一下
js原型:
JavaScript规定,每一个函数都有一个prototype对象属性,其指向另一个对象(原型链上)。prototype上的所有属性和方法,都会被构造函数的实例继承。我们可以把不变的公用的属性和方法,直接定义在prototype对象属性上。

原型链:
实例对象与原型之间的连接,叫做原型链。
__ proto __(隐式连接)属性是每一个对象以及函数都隐含的一个属性。对于每一个含有__proto__属性,他所指向的是创建他的构造函数的prototype。原型链就是通过这个属性构件的。

function Pro() {
  //...
}
var pro = new Pro();

其中 Pro 中有 prototype 属性,而 pro 没有,但是在 pro 中隐含的__proto__属性指向 Pro.prototype。
即有:

pro.__proto__ === Pro.prototype; //true

__proto__属性是每一个对象以及函数都隐含的一个属性。对于每一个含有__proto__属性,他所指向的是创建他的构造函数的prototype。原型链就是通过这个属性构件的。

function A() {
}
function B() {
}
var a1 = new A();
B.prototype = a1;
var b1 = new B();

可以链式的查找:

b1.__proto__ === a1; //true
b1.__proto__.__proto__ === A.prototype; //true
b1.__proto__.__proto__.__proto__ === Object.prototype; //true

2. 类的创建(es5)
首先new一个function,在这个function的prototype中添加属性和方法。
创建一个Animal类:

//定义一个动物类
function Animal(name) {
	this.name = name;  //属性
	this.sleep = function() {   //实例方法
		console.log(this.name + 'sleep...');
	}
}
//在原型链上添加一个原型方法
Animal.prototype.eat = function(food) {
	console.log(this.name + 'eat...' + food)
}

3. 类的继承

  • 原型链继承:

原型链继承是JavaScript实现继承的主要方法。利用原型让一个引用类型继承另一个引用类型的属性和方法。

//创建一个空对象
function Cat() {
}
Cat.prototype = new Animal();
Cat.prototype.name = 'cat';
var cat = new Cat;

通过控制台可以观察到:
在这里插入图片描述
打印cat对象发现其实例继承了Animal的属性和方法。
特点:基于原型链,既是父类的实例,也是子类的实例。
缺点:不能实现多继承。

  • 构造继承:

使用父类的构造函数来增强子类实例,等于是复制父类的实例属性给子类(没用到原型)。

function Cat() {
    Animal.call(this);
    this.name = name || 'cat';
}
var cat = new Cat();

控制台观察:
在这里插入图片描述
可以看到继承了来自父类的属性(name)和方法(sleep()),但没有继承原型链上定义的方法eat()。进一步验证:
在这里插入图片描述
特点:可以实现多继承。
缺点:只能实现继承父类的属性和方法,不能继承原型链上的属性和方法。

  • 组合继承:
    相当于构造继承和原型链继承的组合体。通过调用父类构造,继承父类的属性并保留传参的优点,然后通过将父类实例作为子类原型,实现函数复用。
function Cat() {
    Animal.call(this);
    this.name = name || 'cat';
}
Cat.prototype = new Animal();
Cat.prototype.constructor = Cat;
var cat = new Cat();

控制台输出,通过对比前面介绍的原型链继承的控制台输出,可以明显的发现其调用了两份父类构造函数。
在这里插入图片描述

缺点:调用了两次父类构造函数,生成了两份实例。

  • 寄生组合继承:
    可以说是组合继承的优化。通过寄生方式,砍掉父类的实例属性,这样,在调用两次父类的构造的时候,就不会初始化两次实例。
function Cat() {
    Animal.call(this);
    this.name = name || 'cat';
}
(function() {
    //创建一个空对象
    var Super = function() {};
    //将实例作为子类的原型
    Super.prototype = Animal.prototype;
    Cat.prototype = new Super();
}) ()
var cat = new Cat();

控制台输出:
在这里插入图片描述


持续更新。。。

原创文章 9 获赞 30 访问量 2267

猜你喜欢

转载自blog.csdn.net/le__seul/article/details/105719300