继承

继承: 首先继承是一种关系,类(class)与类之间的关系,JS中没有类,但是可以通过构造函数模拟类,然后通过原型来实现继承。继承也是为了数据共享,JS中的继承也是为了实现数据共享。下面介绍三种继承方法。

通过改变原型指向实现继承

这是一个Person构造函数,用于构造Person类的对象:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function Person(name,age,sex) {
this.name=name;
this.sex=sex;
this.age=age;
}
Person.prototype.eat=function () {
console.log("人可以吃东西");
};
Person.prototype.sleep=function () {
console.log("人在睡觉");
};
Person.prototype.play=function () {
console.log("生活就是不一样的玩法而已");
};

这是一个Student构造函数,用于构造Student类的对象:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function Student(name,age,sex,score) {
this.name=name;
this.sex=sex;
this.age=age;
this.score = score;
}
Student.prototype.eat=function () {
console.log("吃东西");
};
Student.prototype.sleep=function () {
console.log("在睡觉");
};
Student.prototype.play=function () {
console.log("在玩耍");
};
Student.prototype.study=function () {
console.log("学习很累很累的哦.");
};

可以看见,Student构造函数的很多属性和Person构造函数的属性是一致的,这样就造成了一种冗余。因此,可以让Student继承Person来减少冗余:

1
2
3
4
5
6
7
8
9
10
function Student(score) {
this.score=score;
}
//改变学生的原型的指向即可
Student.prototype=new Person("小明",10,"男");
Student.prototype.study=function () {
console.log("学习很累很累的哦.");
};

var stu=new Student(100);//创建Student实例

借用构造函数来实现继承

​ 为了数据共享,改变原型指向,做到了继承—通过改变原型指向实现的继承,但是这种方法有个缺陷:因为改变原型指向的同时实现继承,直接初始化了属性,继承过来的属性的值都是一样的了,所以。这就是问题,只能重新调用对象的属性进行重新赋值,显然这样太麻烦了。

解决方案:继承的时候,不用改变原型的指向,直接调用父级的构造函数的方式来为属性赋值就可以了:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
   function Person(name, age, sex, weight) {
this.name = name;
this.age = age;
this.sex = sex;
this.weight = weight;
}
Person.prototype.sayHi = function () {
console.log("您好");
};

function Student(name,age,sex,weight,score) {
//借用构造函数
Person.call(this,name,age,sex,weight);
this.score = score;
}

var stu1 = new Student("小明",10,"男","10kg","100");
console.log(stu1.name, stu1.age, stu1.sex, stu1.weight, stu1.score);

var stu2 = new Student("小红",20,"女","20kg","120");
console.log(stu2.name, stu2.age, stu2.sex, stu2.weight, stu2.score);

var stu3 = new Student("小丽",30,"保密","30kg","130");
console.log(stu3.name, stu3.age, stu3.sex, stu3.weight, stu3.score);

stu3.sayHi();//报错!无法调用父级构造函数的方法,因为无法继承方法

事实上,这个方法却带来了另一个缺陷:父级类别中的方法不能继承!!!

组合继承

​ 原型实现继承

​ 借用构造函数实现继承

​ 组合继承:原型继承+借用构造函数继承

组合继承的方法是比较好的一种方式,避免了上述两种方式的缺陷。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
function Person(name,age,sex) {
this.name=name;
this.age=age;
this.sex=sex;
}
Person.prototype.sayHi=function () {
console.log("很高兴见到你");
};
function Student(name,age,sex,score) {
//借用构造函数:属性值重复的问题
Person.call(this,name,age,sex);
this.score=score;
}
//改变原型指向----继承
Student.prototype=new Person();//不传参数值。
Student.prototype.eat=function () {
console.log("吃东西");
};
var stu=new Student("小黑",20,"男","100分");
console.log(stu.name,stu.age,stu.sex,stu.score);
stu.sayHi();
stu.eat();
var stu2=new Student("小白",18,"男人","85分");
console.log(stu2.name,stu2.age,stu2.sex,stu2.score);
stu2.sayHi();
stu2.eat();

//属性和方法都被继承了

拷贝继承

拷贝继承:把一个对象中的属性或者方法直接复制到另一个对象中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function Person() {
}
Person.prototype.age=10;
Person.prototype.sex="男";
Person.prototype.height=100;
Person.prototype.play=function () {
console.log("玩的好开心");
};
var obj2={};
//Person的构造中有原型prototype,prototype就是一个对象,那么里面,age,sex,height,play都是该对象中的属性或者方法

for(var key in Person.prototype){
obj2[key]=Person.prototype[key];
}
console.dir(obj2);
obj2.play();



(完)