javascript原型链详解(js中原型和原型链)
一、原型
1.函数原型
在JavaScript中,函数不仅仅是一个可以重用的代码块,而且还可以作为一种数据使用。在堆空间中为函数分配了它的存储空间,函数名或函数的其他形式的引用保存了这个存储空间的引用地址。所以JavaScript中的函数是一种引用数据类型,这就是为什么我们说JavaScript中的函数也是对象。
那么函数这样的对象有很多特殊的性质,原型就是其中之一。每一个函数对象都包含一个属性:prototype。当我们声明一个函数时,函数对象就创建好了。而函数对象创建的同时,系统还会同时创建一个对象,并让函数对象的prototype属性指向它。
比如说,当我们执行下面代码时:
但是更深层次挖掘一下,我还需要知道创建函数对象的同时,还会创建一个“原型对象”,由函数对象的prototype属性指向这个原型对象。
2.对象原型
函数可以和以它为构造器所创建的所有对象共享原型对象。就比如本文最初展示的代码中,per01和per02都是Person函数创建的,那么per01或per02就可以通过自身的__proto__属性关联到Person对象的原型。
下图表示了它们之间的关系
所以既然函数的原型对象是可以为所有被创建对象共享的,那么就可以将我们要为所有对象都添加的属性添加到原型对象上。
二、原型链
在研究了对象原型和函数原型的关系后,我们还可以进一步深入思考:既然原型对象是一个“对象”,那么这个对象有没有__proto__这个属性呢?当然有!
但原型链并不是无止境的,到Object()函数为止。
三、原型的作用
JavaScript中原型有很广泛的用途,在此我们仅举两例,供大家参考。
1.格式化日期
在JavaScript中对日期格式化的支持不是很完善,需要我们自己弥补。但是用到日期格式化的地方又很多,这毕竟是个基础操作,那如何能够一劳永逸的解决这个问题呢?
①通过原型机制将格式化日期的函数添加到Date()函数对象上
代码如下:
②将上述代码保存到js文件中
③使用时引入这个js 文件即可调用format()函数格式化日期
2.模拟继承
在JavaScript中没有类的概念,用于创建对象的构造器函数很类似于Java中的类。而面向对象中的很多思想在JavaScript中也只能模拟实现。
①情景举例
声明一个Person构造器函数和一个Student构造器函数。
很明显,这两个函数从语义上来说存在着继承关系,学生是人的一种,Student对象应该是Person对象的实例。同时给姓名和年龄赋值的语句在两个函数中也是重复的。
所以模拟继承时我们需要解决两个问题:
i.将Student中的重复代码使用Person来代替
ii.让Student对象是Person的实例,即student instanceof Person要返回true
②提取重复代码
③instanceof
那么这是为什么呢?在JavaScript中,判断一个对象是否是某个构造器函数的实例,就是看分别沿着对象和函数的原型链能否找到同一个原型对象。
例如:student对象为什么能够是Object的实例呢?
那么现在student.__proto__和Person.prototype相等,student自然就可以是Person的实例了。
