xiaocaibai 2016-03-31
Javascript没有提供继承的机制,但是提供了方法使其可以做到继承一个类,具体做法是:
//Shape - superclass function Shape() { this.x = 0; this.y = 0; } Shape.prototype.move = function(x, y) { this.x += x; this.y += y; console.info("Shape moved."); }; // Rectangle - subclass function Rectangle() { Shape.call(this); //call super constructor. } // 下面将父类的prototype拷贝一份给自己,否则子类进行prototype的修改时,其实就是在修改父类的prototype,这就不是继承了 Rectangle.prototype = Object.create(Shape.prototype); Rectangle.prototype.constructor = Rectangle; // 不设置的话会指向Shape var rect = new Rectangle(); rect instanceof Rectangle //true. rect instanceof Shape //true. rect.move(1, 1); //Outputs, "Shape moved."
参考网址:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/create
需要指出的是:Shape.call(this);确保用new创建对象时,父类Shape的构造函数得以执行,而Rectangle.prototype = Object.create(Shape.prototype);是将父类Shape的prototype复制一份给子类Rectangle,使用这种方法以后,如果后面的代码修改了父类,则不会影响到子类了。如果希望父类子类公用同一套代码和数据,可以写成:Rectangle.prototype = Shape.prototype; 但是要注意的是,这样一来,子类做的任何修改都会影响到父类,这就不是继承了,所以,应该采用Object.create的方法,使得子类继承了父类的方法,并且能够对子类的prototype的各种方法进行添加和修改。
另外就是要设置子类的prototype.constructor 等于子类,否则这个值就是父类了。
设置constructor并不影响javascript对象的任何行为,这个constructor其实是一个历史遗留的副产品,没有多大用处。见如下描述:
但又有说constructor有用处的,比如下面的描述:
不过这么怪异的用法使得我实在不想这样编程。对于面向对象的编程来说,修改类的行为,为什么要通过一个对象去改变。为什么要将类闭包呢。
另一方面来说,编程为了严谨,则要设置子类的constructor指向子类,否则看起来,子类就有数据不一致的情况了。毕竟通过对象的constructor,访问到父类,是不对的。
举个使用对象修改了类的例子:
function base() { } base.prototype.show = function(){ alert("OK") } function Child (){ this.cname = "UUUU"; base.call(this); } Child.prototype = Object.create(base.prototype); Child.prototype.constructor = Child; var c = new Child(); c.constructor.prototype.display = function(){ alert(this.cname); } var d = new Child(); d.display();