var Person = new Person(); person.prototype.sayHi = function() { alert("hi"); }; person.sayHi();
原来看以上代码总是觉得很神奇,如果是在C或是C++中是不可能在创建对象后还能够在对象创建之后访问类新添加的属性方法。在Js中,这个person.sayHi()不仅不会报错反而会正常执行弹出hi的窗口。在内存中,每个对象或是每个实例都通过一个_proto_的指针访问相应的property,这就有点类似于C++里面的动态调用亦或是动态联编,通过指针来动态的访问内存的数据。但是更让我咂舌的是下面一段代码:
function Person() {} var person = new Person(); Person.prototype = { constructor : Person, name : "Summer", age : 29, sayName : function() { alert(this.name); } }; person.sayName(); //error
此处出错的原因在于我们重写原型后任何原型与之前存在的对象实例之间的关系已经中断,而它们依然引用的是最初的原型,而最初的原型中不包含sayName()以及其他重写的属性而是一个光板的Person模型,自然要报错。
但是,似乎以上两段代码有一些说不清道不明的别扭,第一个与第二个的区别在于,第一个对然对原型有所改变但是指针指向的原型是在发展变化的而我们看到的第二个在完全重写后,先前创建的实例指向的原型是没哟改变的,因为原型对象已经变了不是原来的原型对象指针指向的地址也必然不一样。有一点必须注意的就是constructor属性是为了确保通过该属性能访问到确切的值。重写默认原型对象造成的结果是新的constructor属性指向新的原型对象的constructor即Object。
而在面向对象的继承中,关键也是在于这个继承,只需要让子类的原型对象有指向父类原型的指针就行了,所以最好的办法是直接用SubType.prototype = new SuperType();当然还有类似于Java中的子类中使用super方法来构造继承,此处我们也可以用SuperClass.call(this,arguments...)来实现我们的继承。