最近在学习PHP的类,对封装,继承和多态有了进一步的认识,于是反过来学习Javascript中面向对象的方法,想把这一部分原来没有理解的,彻底弄明白。PHP和Javascript的封装在博客中进行了对比,可以说这一块还是比较好理解的。但是到了继承这一块,理解起来就有点难度,主要是集中在__proto__,prototype,constructor这三个属性的理解方面。Constructor比较好理解,就是一个构造函数,那么其它两个属性的含义呢?
最先遇到问题的是下面一个例子:
<script> function Human(){ this.height=180; this.say=function(){ alert("我在说话"); } } var he=new Human(); alert(he.prototype); </script>
这个例子总结总结出来的问题就是:为什么实例化的对象没有prototype属性?
第二个问题就是:prototype和__proto__到底有什么区别?
首先,看到了这样一幅图:
英文是这样说的:
prototype is a property of a Function object. It is the prototype of objects constructed by that function.
__proto__ is internal property of an object, pointing to its prototype. Current standards provide an equivalent Object.getPrototypeOf(O) method, though de facto standard __proto__ is quicker.
Prototype是一个对象的属性,它是由这个对象创建的子对象的原型
__proto__是一个对象的内部属性,指向它的原型,也可以通过Object.getPrototypeOf()来获取对象的原型,但是用__proto__更快。
有点拗口,意思就是__proto__属性指向的才是自己的原型,而prototype是父对象的属性,子对象是继承父对象的prototype属性指向的对象的属性和方法。那么实际上,整个继承的过程就是,当我访问一个对象的属性时,首先会查找这个对象有没有属性,如果有的话,直接取出,如果没有的话,通过这个对象的__proto__属性指向的对象查找此对象(即第一个对象的父对象)的属性,有的话返回,没有的话,继续往上查找,直到返回属性值或者空(这是JS对象的属性查找的内部实现)。
那么父对象的prototype这个属性的作用是什么呢?我们可以直接通过给对象的__proto__属性赋值来操作继承啊,如下:
<script> function Human(){ this.height=180; this.say=function(){ alert("我在说话"); } } var he=new Human(); he.__proto__.age=20; var she=new Human(); alert(she.age); //返回20 alert(he.age); //返回20 </script>
通过指定实例化对象he的原型的属性age,she一样可以访问,看来要prototype这个也没什么作用啊?
实际上,__proto__这个对象的属性是对象的内部属性,是火狐最先开放出来的,现在只有火狐和Google浏览器支持,IE是不能访问的,所以,我们不能依靠这个去给对象的原型赋值来达到继承,只能绕一下,通过父对象的prototype属性来访问自对象的原型,进而实现集成。也就是说, 子对象.__proto__===父对象.prototype
那么到这里,第二个问题,“prototype和__proto__到底有什么区别?”已经解决了。第一个问题,“为什么实例化的对象没有prototype属性?”还没有解决,我会在接下来的博客中继续讲这个问题。
评论列表: