今天想再深入理解一下原型继承,发现以下这两种继承方式都没什么问题,请问大牛们,这两种方式有区别吗,区别是啥?
function People(){}
People.prototype = {role : 'user'}
function Male(){}
Male.prototype = People.prototype;
var m = new Male()
m.role // 输出 user
m instanceof People // 输出 true
function People(){}
People.prototype = {role : 'user'}
function Male(){}
Male.prototype = new People(); // 这里跟上面定义方式不同
var m = new Male()
m.role // 输出 user
m instanceof Male
有区别!
原形链不一样。第一个的原型链是:
m->People.prototype
,第二个的原型链是:m->{// People实例}->People.prototype
提问者提问:这两种写法除了原型链条上的区别外,如果在运用到实际的工作中,会不会遇到坑?
会!!第一种比较可能遇到坑!看代码:
第一种继承实现:
第二种继承实现:
当然对于第一种继承实现,也是有方法避免报错的:
总结:在javascript的原型继承的世界里,这是十分灵活自由的,所以当然也会存有很多很多的坑。对于很多初学者或小白(比如我)是很难明白那种方法比较正统,也很难明白那种方法比较正确,但这不重要,毕竟这些
‘哲理’上的东西需要经验的积累
,但至少需要知道当发生报错时,究竟是什么错并如何解决!
PS:对于第二种继承实现和对第一种继承实现的完善同样是有区别的。
可以参考下
ruanyf
的http://www.ruanyifeng.com/blog/2010/05/object-oriented_javascript_inhe...经我思考,
Male.prototype = People.prototype
的方式不可用,因为Male继承自People,但是Male还需要具备自身所拥有的属性,如果直接使用Male.prototype = People.prototype
的方式,未来会污染到父类原型链,比如我给Male.prototype.role = 'male user'
,那么所有的People.prototype
都被污染了!因为
Male.prototype
是一个原型引用,改变引用类型,所有的引用都会改变。因此,
Male.prototype = new People()
才是正统!一个网友建议使用:
Male.prototype = Object.create(People.prototype)
我觉得也是赞赞的。JavaScript的继承是基于原型链而非“类”,其所谓继承不过是在原型链中查找其本身不存在的属性而已。
目前最有效的设计,是在子类型中调用父类型构造函数,同时指定子类型的prototype属性为一个以父类型的prototype为原型的对象,这样可以构建合理的原型链。
还是拿传统的动物来举例:
如上我们建立了一个Animal类型,其name属性由参数name确定,其实例的原型中的type属性由Animal.prototype.type来确定。
下面将建立一个Dog类型,继承自Animal:
为方便继承可以采用如下函数: