发布网友 发布时间:2022-04-22 03:21
共1个回答
热心网友 时间:2022-04-22 11:16
先举一个非常简单的例子,我有一个类叫Humans(人类),然后我有一个对象叫Tom(一个人)和另一个对象叫Merry(另一个人),很明显Tom和Merry都是由Humans这一个类实例化之后得到的,然后可以把这个例子写成如下代码:functionHumans(){this.foot=2;}Humans.prototype.ability=true;varTom=newHumans();varMerry=newHumans();alert(Tom.foot);//结果:2alert(Tom.ability);//结果:truealert(Merry.foot);//结果:2alert(Merry.ability);//结果:true以上是一个非常简单的面向对象的例子,相信都能看懂,如果尝试修改Tom的属性ability,则functionHumans(){this.foot=2;}Humans.prototype.ability=true;varTom=newHumans();varMerry=newHumans();Tom.ability=false;alert(Tom.foot);//结果:2alert(Tom.ability);//结果:falsealert(Merry.foot);//结果:2alert(Merry.ability);//结果:true以上可以看出Tom的ability属性的值改变了,但并不影响Merry的ability属性的值,这正是我们想要的结果,也是面向对象的好处,由同一个类实例化得到的各个对象之间是互不干扰的;OK,接下来给ability换成object对象又如何?代码如下:functionHumans(){this.foot=2;}Humans.prototype.ability={run:'100米/10秒',jump:'3米'};varTom=newHumans();varMerry=newHumans();Tom.ability={run:'50米/10秒',jump:'2米'};alert(Tom.ability.run);//结果:'50米/10秒'alert(Tom.ability.jump);//结果:'2米'alert(Merry.ability.run);//结果:'100米/10秒'alert(Merry.ability.jump);//结果:'3米'以上代码就是在原型链上使用了对象,但从以上代码可以看出Tom的ability属性的改变依然丝毫不会影响Merry的ability的属性,于是乎你会觉得这样的做法并无不妥,为什么说不能在原型链上使用对象?接下来的代码就会显得很不一样,并且可以完全表达出原型链上使用对象的危险性:functionHumans(){this.foot=2;}Humans.prototype.ability={run:'100米/10秒',jump:'3米'};varTom=newHumans();varMerry=newHumans();Tom.ability.run='50米/10秒';Tom.ability.jump='2米';alert(Tom.ability.run);//结果:'50米/10秒'alert(Tom.ability.jump);//结果:'2米'alert(Merry.ability.run);//结果:'50米/10秒'alert(Merry.ability.jump);//结果:'2米'没错,从以上代码的输出结果可以看出Tom的ability属性的改变影响到Merry的ability属性了,于是就可以明白在原型链上使用对象是非常危险的,很容易会打破实例化对象之间的相互性,这就是为什么不能在原型链上使用对象的原因?是的,但我想说的可不只如此,而是其中的原理,看完后面JS原型链的深层原理之后,相信你会完全明白。在以下第二部份解释JS原型链的深层原理之前,先来明确一个概念:原型链上的属性或方法都是被实例化对象共用的,正因如此,上面的Tom.ability.run='50米/10秒',改动了原型连上的ability才导致另一个对象Merry受影响,既然如此,你可能会问Tom.ability={}不也是改动了原型链上的ability吗,为什么Merry没有受影响?答案是Tom.ability={}并没有改动原型链上的ability属性,而是为Tom添加了一个自有属性ability,以后访问Tom.ability的时候不再需要访问原型链上的ability,而是访问其自有属性ability,这是就近原则。