说原型之前,我得把其他东西先理清,所有用function创建出来的对象都有一个prototype对象,比如:
1 function Person() {};
2 var Person = new function () {};
JavaScript提供的所有内置对象,Object,Array,Function,RegExp这些构造函数类型都是 function ,都属于函数对象
但是这其中还有区别,以Array为例,用以下三种方法创建变量:
1 var a1 = [1,2,3]; 2 var a2 = new Array(1,2,3); 3 var a3 = Array(1,2,3);
这三者之间,互不相等,但都是Object类型,只是引用的地址值不同,是三个不同的对象 同样的还有Object和Function
1 console.log(a1 == a2);//false 2 console.log(a1 == a3);//false 3 console.log(a2 == a3);//false
但String,Number,Boolean三种与其他不同,以String类型为例,用三种方式创建变量
var a1 = "123"; var a2 = new String(123); var a3 = String(123);
这三种当中,值全部互相相等,但是a1和a3是String类型,a2是Object类型,所以比较全等(===)的时候,只有a1和a3全等
1 console.log(a1 === a2);//false 2 console.log(a1 === a3);//true 3 console.log(a2 === a3);//false
Number,Boolean同理
总结:所有构造函数,只要用new方式实例化,那他的实例是Object类型。如果用其他方式的话,String,Number,Boolean是自己自身的类型,其他均为Object类型。
一、对象的原型
原型就是在自定义构造函数创建的时候,系统默认添加的一个名为prototype的对象,这个对象中默认有一个costructor的属性,可以返回创建这个对象的构造函数的引用,还有一个没有被w3c认可的__proto__属性,他可以返回原型对象的原始对象,说着我都觉得绕...明明没这么难理解的...差不多就是这么个图
所有函数对象的原型对象都继承自他的原始对象,也就是说Person.prototype.__proto__指向的是他的上一级的原型,在chrom中的显示如下图:
可以看出它的上一季的原型是Object函数的原型Object.prototype。而实际上Object.prototype是所有对象的原始对象,这个原始对象他的__proto__属性是null,算得上是原型里的万物起源了,一般用Object.prototype表示原始对象
1 console.log(Person.prototype.__proto__ == Object.prototype);//true 2 console.log(Array.prototype.__proto__ == Object.prototype);//true 3 console.log(String.prototype.__proto__ == Object.prototype);//true 4 console.log(Function.prototype.__proto__ == Object.prototype);//true 5 console.log(Object.prototype.__proto__ == Object.prototype);//false 6 console.log(Object.prototype.__proto__);//null
Object和Function之间的关系比较复杂,借用知乎上的一张图,可以很好地理清这里边的关系
由于函数对象Function的特殊性,会有这样的关系:
1 console.log(Function.prototype === Object.__proto__);//true 2 console.log(Function.prototype === Function.__proto__);//true 3 console.log(Function.prototype.__proto__ === Object.prototype);//true
所有的构造函数都是Function对象的实例,Object是Function的一个实例,并且Function.prototype是Object对象的一个实例的原型对象,实例对象的原型会指向其构造函数原型的prototype属性, 所以就有了 Object.__proto__ === Function.prototype, Function.__proto__ === Function.prototype, Function.prototype.__proto__ === Object.prototype,觉得绕的话还是看图,记住就行了,记不住就翻出来看看
二、原型链
使用new得到的对象的实例,他的__proto__属性会指向被实例化的对象的原型对象,而函数对象的原型对象又继承自原始对象
function Person() { } var p = new Person(); console.log(p.__proto__);//Person.prototype console.log(p.__proto__.__proto__);//Object.prototype console.log(p.__proto__.__proto__.__proto__);//Object.prototype.__proto__ null
原型链其实想一个金字塔,越往上,原型方法越少,越往下,原型方法被扩充的越多。这种用__proto__链接,最终指向Object.prototype.__proto__的逻辑链,就是原型链,JavaScript用这种方式实现数据的继承
理解可能比较片面,如有不当,还请指正