梳理javascript中prototype(原型)、class(类)、constructor(构造函数)

可能有些人会觉得题目中的这些概念比较难理解,其实我一直觉得,概念难理解关键在于没有针对概念进行实践,或者说在我们工作中很少涉及到对这些概念理解的实践。概念就向一个黑盒子,我们需要在外进行实践,才能做到深刻理解。今天我会尽力去通过实践来让这些概念容易被理解,Let’s go!

1.说说Class(类)

学过java,C#等编程语言的,对这个概念并不陌生,它就是一类具体事物的抽象,概括。在javas,C#这些高级语言里面可以直接定义类,并且给类添加各种方法,属性等成员。类和类之间可以继承,调用等。在javascript里面,类的概念没有变,只是有些不同。那就是javascript里面类是和prototype息息相关的,prototype是javascript语言提供的一个对象。javascript类具体的定义:类是一个集合,这个集合包含一个或多个对象,这些对象都继承自同一个prototype。我认为正是有了prototype及其相关的特性,才使得javascript是一个面向对象的语言,prototype是javascript类的核心。

 

2.定义一个Class

准确的说是创建一个类的实例,那这里需要两个条件:①能够实例化,给对象分配内存,这里可以使用new关键字 ②prototype是同一个

这里定义一个函数CreateObjFrom(obj)

 

obj1和obj2两个对象拥有的成员是完全一样,prototype是一样的。当然obj1===obj2为false,我们需要知道一个常识,对象属于引用类型,相等比较的是引用类型的地址。两个对象当然分配了两个内存地址,所以这里使用===判断返回false。当然我们如果想判断两个对象的成员是否一样,从这个意义上来视为“相等”可以循环遍历每个对象里面成员比较值是否一样,有一个类库可以使用Underscore.js(_.isEqual())。

 

当然这里使用了Object.create方法,这个方法在ES5里面规定的。如果要兼容低版本,需要做下判断。改善后的代码如下:

 

3.constructor(构造函数)和class(类)

其实Object.create方法为我们提供了一种创建对象的途径,虽然不是很常用。第二种创建对象的方式:通过构造函数。构造函数就是专门用来创建新对象的,当然必须配合new关键字调用,没有使用new调用构造函数,只是把构造函数当作了一个普通的函数调用,这里有一个约定:构造函数首字母大写。新对象的prototype就是constructor的prototype。具体通过代码实例说明prototype在new创建新对象时的过程:

控制台输出:

说明构造函数Aaa的prototype传递给了新对象b,并且存放在b.constructor.prototype中。而b对象下没有直接属性prototype,b.prototype为undefined。

 

3.1 new Aaa;这句包含2个过程:①new创建了一个新对象(object) ②构造函数调用,b的构造函数就是Aaa,构造函数的prototype就是Aaa的prototype。代码说明:

控制台输出:

这个结果肯定是毋容置疑的,b本来就是通过Aaa new出来的。所有构造函数肯定是Aaa,Aaa的prototype肯定也是一致的。如果要找原理,也只能在prototype里面去找,Aaa.prototype.constructor就是Aaa,而这个prototype传递给了b,b的constructor才是Aaa。下图可以说明:

任何javascript函数都可以作为构造函数,每一个javascript函数都会有prototype属性(除了使用Function.bind方法创建的新function木有prototype属性)。代码说明如下:

  

 

3.2 特别提到一个运算符instanceof:b instanceof Aaa 返回true,并不代表b是Aaa构造函数初始化的,而是表示b继承了Aaa的prototype。

 

4. constructor,prototype,类的实例三者之间的关系如下:

5.javascript原型的根是Object的prototype,所有的对象都是继承了Object的原型。如果进行一些修改,代码如下:

控制台输出:

说明如果构造函数的prototype被重写而且没有指定constructor属性为原来的构造函数,这时新对象会从Object继承。如果只是给原型添加属性,例如这样写:Aaa.prototype.showMsg=function(){},这样不会导致上面的结果。

5.1 javascript的类是动态的,可变的,可以给构造函数的prototype增加一些功能来增强类,可以称javascript类型是”duck-typing”。

 

希望通过这篇文章给大家理解这些概念有点帮助,欢迎大家留言交流。

javascript
作者:张雪飞
出处:https://zhangxuefei.site/p/785
版权说明:欢迎转载,但必须注明出处,并在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

发表评论

电子邮件地址不会被公开。 必填项已用*标注