阅读javascript高级编程中, 对动态原型法中写Prototype继承父类对象的不可行的现象,不甚理解。
书上说是技术原因,如下有问题代码:
但是把protype语句移到构造函数后面,就OK,如下图:
找到代码 https://raw.githubusercontent.com/nzakas/professional-javascript/master/edition1/ch04/DynamicPrototypePolygonExample.htm
通过实验确定有如下解释:
1、 Prototype就是一个对象,对象中的所有的属性和方法, 都是实例化的内容。
2、 构造函数在被new生成的时候,此实例的Prototype对应,new之前此类的Prototype。
3、 构造函数中,修改Prototype,不影响即将诞生的实例的Prototype按照之前的内容生成。
如果将Triangle Prototype赋值,放在构造函数中, 则第一次new动作的时候, 此类的Prototype对象是空对象 {},
没有任何属性和方法,则第一次new出的实例的Prototype为 {}, 没有 getArea 函数;
但是第一次执行之后, Prototype 切换为 new Polygon 对象, 且不再改变, getArea 函数也被重载, 在第二次及之后的new Triangle都是有 getArea 方法的。
测试代码:
<html> <head> <title>Example</title> </head> <body> <script type="text/javascript"> function Polygon(iSides) { this.sides = iSides; console.log("con poly") if (typeof Polygon._initialized == "undefined") { Polygon.prototype.getArea = function () { return 0; }; Polygon._initialized = true; } } function Triangle(iBase, iHeight) { Polygon.call(this, 3); this.base = iBase; this.height = iHeight; if (typeof Triangle._initialized == "undefined") { /* 只要有对 Prototype 指向对象的修改, 则继承和覆盖都不生效 */ //Triangle.prototype = new Polygon(); /* 如果仅仅是从Polygon实例中获取方法, 并赋值给Prototype,则是OK的 */ var pobj = new Polygon(); Triangle.prototype.getArea = pobj.getArea; Triangle.prototype.getArea = function () { return 0.5 * this.base * this.height; }; Triangle._initialized = true; } } function Rectangle(iLength, iWidth) { Polygon.call(this, 4); this.length = iLength; this.width = iWidth; if (typeof Rectangle._initialized == "undefined") { Rectangle.prototype.getArea = function () { return this.length * this.width; }; Rectangle._initialized = true; } } /* retangle 非动态原型中实现继承 OK */ Rectangle.prototype = new Polygon(); /* 构造函数中Prototype对象没有改变, 在构造函数中有对getArea修改, 不影响实例化的对象有getArea */ var Polygon = new Polygon(12); alert("Polygon.sides="+Polygon.sides) alert("Polygon.getArea="+Polygon.getArea()) var triangle = new Triangle(12, 4); /* 动态原型法中,只要有对 Prototype 指向对象的修改, 则继承和覆盖都不生效,对于第一次new不生效, 对于第二次生效 */ //var triangle1 = new Triangle(12, 4); var rectangle = new Rectangle(22, 10); alert(triangle.sides); alert(triangle.getArea()); //alert(triangle1.getArea()); alert(rectangle.sides); alert(rectangle.getArea()); </script> </body> </html>