构造函数 与 原型 一直是继承的一个重点,原型也是javaScript的一个特色 , 今天和大家分享一下构造函数的继承,以及函数中原型的概念
原型的概念
在说构造函数之前,我们先来探讨一下我们之前博客中提到的原型, 什么是原型?
在JavaScript中,通过原型可以实现对象的属性继承,这时候就有一个问题,我们没有定义原型,原型是怎么来的?
之前说过,在H5中,一切皆为对象,所以函数也是一种对象,javascript默认的给函数一个属性——prototype。
这个prototype的属性值是一个对象(属性的集合,再次强调!),默认的只有一个叫做constructor的属性,指向这个函数本身。
注意这个prototype属性,这是只有函数才拥有的,其他的对象也有原型使用的是(proto)
原型上填写共有的属性和方法
共有的属性和方法都放在原型里,这样不会占用太多的内存
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| function Dog(name){ this.name = name; } //对这个构造函数的原型进行重新定义,把原来的去掉,注意:会把构造函数一起去掉 Dog.prototype = { family:"金毛", jiao:function (){ alert(this.name + '汪汪汪'); }, construction:Dog //因为原型中缺少呢一个构造函数,所以我们自己加 } //Dog.prototype.construction = Dog; 这样也可以添加构造函数
|
这样就实现了在原型上填写共有的属性和方法,当然,原型也有他自己的缺点:
修改一个地方,任何一个基于该构造函数的对象都会发生改变,所以原型不能进行值的传递
原型的小知识点
关于对象调用属性和方法的顺序,先在自身对象(构造函数)中去找,一直往上,找到直接调用;
isPrototypeOf() 判断原型和对象之间的关系
hasOwnProperty() 对象和属性,方法 之间是否存在关系,该属性,方法 必须是自身的(原型中的不算)
构造函数的继承
继承: 基类(父类)—->派生类,拓展类(子类)
特点: 不仅可以有自己的属性和方法,而且还可以拥有父类的所有属性和方法.并且可以增加自己新的属性和方法
构造函数的继承我把它称之为三步曲:
第一步:构造函数的继承
第二步:原型的继承
第三步:自身构造函数的创建
我们来看一个例子,假设我有个Animal这个类,并且我想让Dog类来继承它,应该怎么实现?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| //先创建一个构造函数(这个构造函数作为父类) function Animal(family){ this.family = family; } //给构造函数的原型加入属性(为了验证子类是否可以继承父类) Animal.prototype.leg =4;
function Dog(family,name){ //第一步:构造函数的继承(使用.call来继承构造函数) Animal.call(this,family); this.name = name; //这是声明子类私有的属性 }
//第二步:原型的继承,这里将Dog的原型全部替换成Animal的原型,注意:构造函数会被删除
Dog.prototype = Object.create(Animal.prototype);
/* Object.create(Animal.prototype)创建出来的是一个空的对象,并且空对象的原型是Animal的原型 所以我们就可以把空的对象作为Dog的原型 */
//第三步:Dog构造函数的创建 Dog.prototype.constructor = Dog;
|
到这里,就将原型和属性全部继承,在第一步中使用到的call,我简单的说明一下
apply 和 call方法的区别
call,apply都是属于function.prototype 的一个方法
call,apply 作用就是借用别人的方法来调用,就像在调用自己的方法一样
相同点:两个方法产生的作用是完全一样的
不同的:方法传递的参数不同
举个简单的例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| function print (a,b,c,d){ alert(a + b + c + d); }
function example(a,b,c,d){
print.call(this,a,b,c,d);//用call方式借用print,参数是打散传递的
print.apply(this,arguments); //用apply方式借用print,参数作为一个数组传递的,这里用的是JavaScript方法内本身有的arguments数组
print.apply(this,[a,b,c,d]); //这样也可以 }
|
ES6的继承
现在来看看另外一种继承方式,ES6的继承
一、ES6的新继承方法
假设我有个People的父类,想要创建一个Man的子类去继承People
extends : 继承的关键字,这里相当于Man这个构造函数继承了People
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| class Man extends People{
constructor(name,age,sex){ // super : 就相当于会自动去执行 People 的构造函数,继承父类 super(name,age);
this.sex = sex;// 新增,扩展自己的属性 }
//这里是Man这个构造函数的新方法 playMJ(){ console.log(this.name + '正在运动'); } }
var man = new Man('小黄',18,'男');//这里实例化的man,可以调用People的方法
|
ES6 的构造函数用法还是很简单的,注意extends 与 super 的用法
以上就是我对构造函数的继承及原型的一些理解,不足之处还望提出,感激不尽