javascript之继承

一、类与对象

1、对象与类

1  var a={};//对象,无法用new实例化
2 function Person(name){
3 this.name=name;
4 }
5 Person.prototype.showName=function(){
6 alert(this.name);
7 }
8 var p=new Person("zhangmeng");
9 p.showName();


组合使用构造函数模式和原型模式实现的类:

构造函数定义属性;原型实现定义方法和属性共享

 1 function Person(name,age,job){
2 this.name=name;
3 this.age=age;
4 this.job=job;
5 this.friends=["y"]//共享属性
6 }//构造函数定义实例属性
7 Person.prototype={
8 constructor:Person,
9 sayName:function(){
10 alert(this.name);
11 }//原型模型用于定义方法和共享属性
12 }
13 var p1=new Person("zhangmeng",24,"Coding");
14 var p2=new Person("jiangyu",26,"Fighting");
15 p1.friends.push("dy");
16 console.log(p1.friends);
17 console.log(p2.friends);
18 p1.sayName();
19 p2.sayName();

2、constructor和prototype

constructor是对象的属性(Object)

prototype是函数的属性(Object),构造函数的prototype指向原型对象,它含有constructor指向构造函数。

3、instanceof和constructor判断对象类型

var d=new Date();

d.constructor==Date;//true

d instanceof Date //true

区别:d instanceof Object;//true

d.constructor==Object;//false

contructor不识别继承的类型

二、继承

1、理解构造函数、原型对象、实例的关系

构造函数中含有原型对象,原型对象包含指向构造函数的指针(constructor);实例中包含内部属性_proto_指向原型对象。

2、原型链继承

 1    function SuperType(){
2 this.property = true;
3 }
4 SuperType.prototype.getSuperValue = function(){
5 return this.property;
6 };//父类
7 function SubType(){
8 this.subproperty = false;
9 }//子类
10 //inherit from SuperType
11 SubType.prototype = new SuperType();
12
13 SubType.prototype.getSubValue = function (){
14 return this.subproperty;
15 };
16 var instance = new SubType();
17 alert(instance.getSuperValue()); //true
18
19 alert(instance instanceof Object); //true
20 alert(instance instanceof SuperType); //true
21 alert(instance instanceof SubType); //true
22
23 alert(Object.prototype.isPrototypeOf(instance)); //true
24 alert(SuperType.prototype.isPrototypeOf(instance)); //true
25 alert(SubType.prototype.isPrototypeOf(instance)); //true

子类通过修改prototype属性,继承父类,实现原型链,而实现继承。当子类实例调用父类方法时候,搜索的步骤是:

1)实例化对象。2)子类方法。3)父类方法。4)Object,所有对象的祖先。

缺点:包含引用类型的原型,包含引用类型的原型属性会被所有实例共享;不能向超类构造函数传递参数。

3、call和apply方法

call和apply都是Function对象的方法,可用来改变对象的内部指针。JS说明如下:

call 方法

调用一个对象的一个方法,以另一个对象替换当前对象。

call([thisObj[,arg1[, arg2[, [,.argN]]]]])

参数:thisObj可选项。将被用作当前对象的对象。arg1, arg2, , argN可选项。将被传递方法参数序列。

说明:call 方法可以用来代替另一个对象调用一个方法。call 方法可将一个函数的对象上下文从初始的上下文改变为由 thisObj 指定的新对象。

如果没有提供 thisObj 参数,那么 Global 对象被用作 thisObj。

apply传入第二个参数是数组形式,如 func.call(func1,var1,var2,var3)对应的apply写法为:func.apply(func1,[var1,var2,var3])

例 var func=new function(){this.a="func"}

var myfunc=function(x){

var a="myfunc";

alert(this.a);

alert(x);

}

myfunc.call(func,"var");// 弹出func和var

4、借用构造函数(Constructor Stealing)实现继承

 1 function SuperType(name){
2 this.name=name;
3 this.colors=["blue","green"];
4 }
5 function SubType(){
6 SuperType.call(this,"zhangmeng");//利用call在SubType的环境下调用SuperType的方法
7 }
8 var instance1=new SubType();
9 instance1.colors.push("black");
10 var instance2=new SubType("jiangyu");
11 console.log(instance1.colors);//blue green black
12 console.log(instance2.colors);//blue green
13 console.log(instance1.name);zhangmeng
14 console.log(instance2.name);jiangyu

缺点:无法实现复用。

5、组合继承(Conbination inheritance)***

构造函数实现对实例属性的继承;原型链实现方法和原型(共享)属性的继承:

 1 function SuperType(name){
2 this.name=name;
3 this.friends=["y"];
4 }
5 SuperType.prototype={
6 constructor:SuperType,
7 sayName:function(){
8 alert(this.name);
9 }
10 }
11
12 function SubType(name,age){
13 SuperType.call(this,name);//构造函数实现对实例属性的继承
14 this.age=age;
15 }
16 SubType.prototype=new SuperType();//原型链实现对原型属性和方法的继承
17
18 SubType.prototype.sayAge=function(){
19 alert(this.age);
20 }
21 var sub1=new SubType("zhangmeng",24);
22 sub1.sayName();
23 sub1.sayAge();
24 sub1.friends.push("dy");
25 console.log(sub1.friends);
26
27 var sub2=new SubType("jiangyu",26);
28 sub2.sayName();
29 sub2.sayAge();
30 sub2.friends.push("xp");
31 console.log(sub2.friends);
32

缺点:两次调用超类构造函数

6 寄生组合式继承(YUI:YAHOO.long.extend)

由于重写类型:SuperType.call(this,name),失去默认的constructor因此重新创建即可代替

SubType.prototype=new SuperType(),

减少一次调用,实现代码:

 1  
2 function inheritPrototype(subType,superType){
3 var prototype=object(superType.prototype);//创建超类原型对象副本
4 prototype.constructor=subType;//弥补由于call方法失去的默认constructor属性
5 subType.prototype=prototype;//子类的prototype指向超类的原型对象
6 }
7
8 function SuperType(name){
9 this.name=name;
10 this.friends=["y"];
11 }
12 SuperType.prototype={
13 constructor:SuperType,
14 sayName:function(){
15 alert(this.name);
16 }
17 }
18
19 function SubType(name,age){
20 SuperType.call(this,name);//构造函数实现对实例属性的继承
21 this.age=age;
22 }
23 //改写为:
24 inheritPrototype(SubType,SuperType);
25 SubType.prototype.sayAge=function(){
26 alert(this.age);
27 }
28 var sub1=new SubType("zhangmeng",24);
29 sub1.sayName();
30 sub1.sayAge();
31 sub1.friends.push("dy");
32 console.log(sub1.friends);
33
34 var sub2=new SubType("jiangyu",26);
35 sub2.sayName();
36 sub2.sayAge();
37 sub2.friends.push("xp");
38 console.log(sub2.friends);