JS之原型式的继承
创建一个person的构造器
function person(first, last, age, gender, interests) { this.name = { first, last }; this.age = age; this.gender = gender; this.interests = interests; };
方法定义在构造器的原型上
person.prototype.greeting = function() { alert('hi! i\'m ' + this.name.first + '.'); };
任务:
创建一个teacher
类,就像我们前面在面向对象概念解释时用的那个一样。这个类会继承person
的所有成员,同时也包括:
- 一个新的属性,
subject
——这个属性包含了教师教授的学科。 - 一个被更新的
greeting()
方法,这个方法打招呼听起来比一般的greeting()
方法更正式一点——对于一个教授一些学生的老师来说。
定义一个teacher的构造器函数
function teacher(first, last, age, gender, interests, subject) { person.call(this, first, last, age, gender, interests); this.subject = subject; }
call()
函数:基本上,这个函数允许您调用一个在这个文件里别处定义的函数。第一个参数指明了在您运行这个函数时想对“this
”指定的值,也就是说,您可以重新指定您调用的函数里所有“this
”指向的对象。其他的变量指明了所有目标函数运行时接受的参数。
最后一行代码简单地定义了一个新的subject
属性,这将是教师会有的,而一般人没有的属性。
创建一个和person.prototype
一样的新的原型属性值
(这个属性指向一个包括属性和方法的对象)
teacher.prototype = object.create(person.prototype);
teacher.prototype
现在会继承person.prototype
的所有属性和方法。
teacher()
的prototype
的constructor
属性指向的是person()
, 我们需要改变一下指向
teacher.prototype.constructor = teacher;
每一个函数对象(function
)都有一个prototype
属性,并且只有函数对象有prototype
属性,因为prototype
本身就是定义在function
对象下的属性。当我们输入类似var person1=new person(...)
来构造对象时,javascript实际上参考的是person.prototype
指向的对象来生成person1
。另一方面,person()
函数是person.prototype
的构造函数,也就是说person===person.prototype.constructor
无参数继承
function brick() { this.width = 10; this.height = 20; }
继承width
和height
属性
function blueglassbrick() { brick.call(this); this.opacity = 0.5; this.color = 'blue'; }
仅传入了this
到call()
中 - 不需要其他参数,因为我们不会继承通过参数设置的父级的任何属性。
总结:
1、随着您的代码量的增大,继承变得重要。如果您开始创建一系列拥有相似特性的对象时,那么创建一个包含所有共有功能的通用对象,然后在更特殊的对象类型中继承这些特性,将会变得更加方便有用。
2、在使用继承时,建议您不要使用过多层次的继承,并仔细追踪定义方法和属性的位置。很有可能您的代码会临时修改了浏览器内置对象的原型,但您不应该这么做,除非您有足够充分的理由。过多的继承会在调试代码时给您带来无尽的混乱和痛苦。
3、对象在您打算把一个数据集合从一个地方传递到另一个地方的时候非常有用。这些都可以在不使用构造器和继承的情况下完成。如果您只是需要一个单一的对象实例,也许使用对象常量会好些,您当然不需要使用继承。