JavaScript——原型链

109 阅读4分钟

1.在js中,所有对象都有自己的原型对象(prototype)。一方面,任何一个对象,都可以充当其他对象的原型;另一方面,由于原型对象也是对象,所以它也有自己的原型。因此,就会形成一个“原型链”:对象到原型,再到原型的原型...直到null为止。

image.png

image.png

2.当读取某个对象的属性时,先在对象本身查找,如果没有就到对象的原型对象上查找,如果对象的原型对象也没有,就到原型对象的原型对象上找,以此类推......

image.png

image.png

直到找到null都没有,那么就返回undefined

image.png

image.png

3.如果对象本身和它的原型对象都定义了一个同名属性,读取时优先读取对象本身的属性。

image.png

image.png

4.对象给一个成员存值时 ,无论其原型链上是否有这个成员 都会把更新或者添加这个成员在对象自己的内存中 ,不会操作原型对象

image.png

image.png

5.系统内置构造函数:Object Function Array Date等; 系统内置的构造函数的原型属性不可以直接替换(代码会被静默) 但是可以添加或者重写其原型对象的成员;自定义的构造函数的原型属性可以随便操作

image.png

image.png

6.笔试题1

image.png

image.png

分析:第一步,最开始就给系统内置构造函数Object和Function的原型对象添加了一个life属性,值分别为1和2;所以之后创建的对象和函数都能访问到life属性。
      第二步,创建了一个函数fn,添加一个name属性为karen
      第三步,使用new关键字:1.创建空对象 2.函数中的this指向创建的空对象  3.函数的返回值为基本数据,所以表达式的值就是创建的对象
      第四步,因为this指向的是创建的对象,因此f1.name=karen;由于表达式得到的是对象,所以f1能访问的是Object的原型对象,所以f1.life=1
      第五步,因为fn是定义的一个函数,而一开始就为所有函数的原型对象添加了life属性,值为2,所以fn.life=2;而函数有默认的name属性,就是函数名,因此fn.name=fn
      

7.笔试题2

image.png

结果:

image.png

分析:1.Child.prototype = new Parent();将new Parent()作为Child函数的原型对象,也就是用Child函数创建的对象都能访问到new Parent()的属性;Child.prototype={a:1,b:[1,2,1],c:{demo:5},show:function(){console.log(this.a,this.b,this.c.demo)},__proto__:{}}
 2.var parent = new Parent();通过new关键字使用Parent函数创建一个新对象,this指向创建的对象,创建的对象能够访问到Parent的属性
3.var child1 = new Child();var child2 = new Child();分别使用new关键字使用Child函数分别创建child1和child2对象,this指向新创建的对象,并且这两个对象的原型对象是new Parent()
4.child1.a = 11; 在child1中添加一个属性a,并赋值为11.
  child2.a = 12;在child2中添加一个属性a,并赋值为12.
5.parent.show();调用parent对象中的show方法,打印出1 [1,2,1] 5
6.child1.show();由于child1对象中没有show方法,所以到其原型对象new Parent()中找;并打印a,b,c.demo的值,但是由于child1里面有a属性,所以就打印它本身的a的值,其余没有的就打印原型对象中对应的值;因此打印 11 [1,2,1] 5
  child2.show()同理可得 ,打印12 [1,2,1] 5
7.child1.change();执行change方法,this指向的是child1。this.b.push(this.a);由于原型对象不能修改但是可以操作,且这一步并没有修改原型对象,只是向原型对象的b属性中添加了一个数据,此时b就变为了[1,2,1,11]。this.a = this.b.length;给child1自己添加/更新a属性 值为child1的原型对象的属性b的长度,为4。this.c.demo = this.a++;先取a的值为4,再赋值给原型对象中的c.demo,最后a再加1变为5.
 child2.change();同理,先再向原型对象的b中增加了a的值12,b就变为了[1,2,1,11,12];并且a又重新赋值为b.length的值,为5;然后再a再加1变为6.
8.parent.show(); 还是打印 1 [1,2,1] 5
child1.show(); 打印 5 [1,2,1,11,12] 5
child2.show(); 打印 6 [1,2,1,11,12] 5