原型
在JS中原型就是prototype对象,用来表示类型之间的关系。
原型链
JS中对象和对象之间是有联系的,通过prototype对象指向父类对象,在指向Object对象。而通过的方式就是_proto_
连接,而_proto_
最终指向null
。
通过四个全局对象来了解原型和原型链
这四个全局对象为:Number()
、String()
、Boolean()
、Object
。
上述四个对象都可以通过下边两种方法实现:
var n1=1
var n2=new Number(1)
var s1='1'
var s2=new String('1')
var b1=true
var b2=new Boolean(true)
var o1={}
var o2=new Object
上述的两种方法区别在内存上的区别。
我们知道1.toString()
会报错,但是这里我们通过n1.toString()
返回的就是字符串'1'
。n1.toString()
方法不会报错,但是n1
只是通过赋值的方法的来的,并没有.toString()
方法。这个时候就是JS通过创建临时对象var temp=new Number(1)
在这个临时对象中对n1
的值进行.toString()
方法,再将得到的返回给n1.toString()
,临时对象用完就自动抹杀。
还有一个例子,我们对n1
进行n1.xxx=2
这是也不会报错,就是用临时方法在heap
内存上创建的,但是再取n1.xxx
时为undefined
。就验证了用完就抹杀,即不存在的原理。
为什么new Number()有.toString()
方法呢?我们打印出n2看看他有没有这个属性。
n2
的值还有一个__proto__:Number
,点开这个属性可以看到萝莉了很多属性,其中就包括.toString()
,所以n2
可以调用.toString()
方法。__proto__:Number
所表示的就是number
共有的属性。此时在图中我们看到
n2.__proto__===Number.prototype
的结果为true
。就是指n2
的__proto__
指向了Number.prototype
,即Number
的共有属性中去,可以从第一张图中可以看到n2
的__proto__
中还有一个__proto__:Object
的隐藏属性。点开就可以看到关于Object的共有属性。综上:我们可以总结出来,当我们
new
出来一个对象的时候,再去使用一个方法时,会首先从它自身的构造函数(或者系统自带函数)的原型对象(函数.prototype
)中去找,如果没有改属性是就会通过__proto__
属性去下一个Object
共有属性中去寻找,直到最后为null
。可以画图理解为:上图中prototype对象就是原型,用过
__proto__
将他们连接就是原型链。即:
对象.__proto__===函数.prototype
其中__proto__
是每个对象都有的一个属性,而prototype
是函数才由的属性。对象具有
__proto__
,可以成为隐式原型,一个对象的隐式原型指向该对象的构造函数的原型。综上有:
var n = new Number();
n.__proto__===Number.prototype//true
n.__proto__.__proto__===Object.prototype//true
n.__proto__.__proto__.__proto__===null//true
String()
、Boolean()
同理,而Object
则是比其他三种少了一个函数.prototype
环节。
易踩坑小知识
var f=false
var f1=new Boolean(false)
if(f){console.log(1)}//无
if(f1){console.log(2)}//2
因为f2
可以看做是对象,对象的Boolean值为true
。所以只会输出2
,没有1
。
网友评论