原型链
1.案例解析
window.object.prototype:里面有很多函数
案例1:该案例为什么不报错,为什么可以运行?
var obj = {}//给了对象obj一个空集
obj.toString()//obj里面的toSring属性
疑问:obj里面是一个空集,里面不会存在toString属性
原因分析:var obj = {}
虽然是一个空集#9011,但里面有一个隐藏属性XX(未知),隐藏属性XX保存了window.Object.prototype
指向的对象#409地址
也就是说:当obj.toString()
在空集中找不到属性时就到xx指向的对象中寻找,于是obj里面的toString就是#409里面的toString
总结1:
- obj有一个隐藏属性
- 隐藏属性存储了Object.prototype对象的地址
- obj.toString()发现obj上没有toString
- 就去隐藏属性对应的对象里面找
案例2
var a = [1,2,3]//a是一个数组,里面存了1,2,3
a.push(4)//给数组a中加一个4
疑问:数组a中只有1、2、3,并没有push,那么4是如何保存进去的?
答:window.array.prototype
指向了对象#9527,而数组a中存在隐藏属性YY,该隐藏属性保存了地址#9527
总结1:
- JS在开天辟地的时候已经在内存里存了
Object.prototype
对应的对象和Array.prototype
对应的对象,这两个对象放到内存里就是用来给用户的隐藏属性XX和YY引用的。 - 当用户创建一个对象,就会引用#409
- 当用户创建一个数组,就会引用#9527
- 这就是JS的光(神说要有光才能创造世界)
一个特例:
obj和obj2对应着同一个对象,那么当obj里面的内容修改后,obj2的会修改吗?
答:不会
那什么时候会改什么时候不会改?
答:一层可以改,两层通过这个方法是不能修改的。
只读不写,obj.toString会在#999中添加一个属性
2.原型
2.1 XXX.prototype存储了XXX对象的共有属性,这就是原型。
- object.prototype就存储了object对象的共同属性
- Array.prototype就存储了Array对象的共同属性
- 共同属性就是原型
- 原型可以i让用户无需重复生命共有属性,有了原型就可以把共有属性提前写到原型上,省代码省内存
- 每个对象都有一个隐藏属性,指向原型(对象,共有属性)
- 如果一个对象是首字母大写的,如Object,那么它就会有一个prototype属性,就不要关心它的隐藏属性(是存在的,但不管),小写的时候(如obj),就要关心其隐藏属性
2.2 隐藏属性叫:__proto__
而prototype
和__proto__
的区别:
- 都存着相同的原型地址
- 不过
prototype
挂在函数上(如Object、Array,一般首字母大写的都是函数) __proto__
挂在每个新生成的对象上(所有对象都有该属性,包括Object、Array、Object.prototype等)