JavaScript中类的继承机制

JavaScript的面向对象编程相比其他语言确实比较麻烦。之前看到,单是类的定义就有很多种方式,而类的继承也有很多方式。这是因为JavaScript中的继承机制并不是明确规定的,而是通过模仿实现的。现把书上提到的方法总结如下代码.其中需要注意的重点已经作为注释标明。其中第五种——混合方式对应定义类的方法中的混合构造函数/原型方式,所以也是最佳的方式。 要用ECMAScript实现继承机制,首先要从基类入手。所有开发者定义的类都可以做外基类。出于安全考虑,本地类和宿主类不能所为基类,这样可以避免访问编译过的浏览器级的代码。
	//此文件说明JavaScript中几种类的继承机制
	//函数 extendsmethodn(n=1:5) 仅为分割代码和测试方便,实际继承方式仅为函数内的代码
	//extendsmethod5();

	//1、对象冒充(call方法和apply方法其实也可看做对象冒充)
	function extendsmethod1(){
		function ClassA(sColor){
			this.color = sColor;
			this.sayColor = function(){
				alert(this.color);
			};
		}

		function ClassB(sColor, sName){
			this.newMethod = ClassA;
			this.newMethod(sColor);	//此处调用传递给ClassB的ClassA方法
			delete this.newMethod;
			//新的属性都要在删除父类对象后再定义
			this.name = sName;
			this.sayName = function(){
				alert(this.name);
			};
		}

		//测试
		var objA = new ClassA("red");
		var objB = new ClassB("blue", "Nicholas");
		objA.sayColor();
		//objA.sayName(); 这句会导致错误,ClassA类没有sayName方法。
		objB.sayColor();
		objB.sayName();

		//继承多个类,假设已存在 ClassX ClassY两个类
		/*
		function ClassZ(){
			this.newMethod = ClassX;
			this.newMethod();
			delete this.newMethod;

			this.newMethod = ClassY;
			this.newMethod();
			delete this newMethod;
		}
		*/
	}

	//2、call()方法
	function extendsmethod2(){
		function sayColor(sPrefix, sSuffix){
			document.write(sPrefix + this.color +sSuffix);
		}

		var obj = new Object();
		obj.color = "red";
		sayColor.call(obj,"The color is ", ", a very nice color indeed.");//call第一个参数为传递给前面的sayColor方法中 this 的对象,后面为传递给sayColor的其他参数
		//输出结果:The color is red, a very nice color indeed. 此例说明 call 方法的用法

		//使用call方法继承
		function ClassB(sColor, sName){
			//this.newMethod = ClassA;
			//this.newMethod(sColor);
			//delete this.newMethod;
			ClassA.call(this, sColor);	//此方法代替上面3行的效果,ClassA定义同对象冒充方法

			this.name = sName;
			this.sayName = function(){
				alert(this.name);
			};
		}
	}

	//3、apply()方法
	function extendsmethod3(){
		function sayColor(sPrefix, sSuffix){
			document.write(sPrefix + this.color + sSuffix);
		};

		var obj = new Object();
		obj.color = "red";
		sayColor.apply(obj,new Array("The color is ",", a very nice color indeed."));	//apply()方法第一个参数仍为obj,即应该赋予sayColor()中的this关键字的值
																							//第二个参数是父类其他参数组成的数组。此例说明apply()方法的用法
		function ClassB(sColor, sName){
			//对象冒充的前三行由一行代替
			ClassA.apply(this, new Array(sColor));	//另外可以用 ClassA.apply(this, arguments); 将ClassB的整个arguments对象作为第二个参数传递给apply()方法,需参数顺序一致

			this.name = sName;
			this.sayName = function(){
				alert(this.name);
			};
		}
	}

	//4、原型链方法
	function extendsmethod4(){
		function ClassA(){
		}

		ClassA.prototype.color = "red";
		ClassA.prototype.sayColor = function(){
			alert(this.color);
		};

		function ClassB(){
		}

		ClassB.prototype = new ClassA();	 //要确保ClassA的构造函数没有参数

		ClassB.prototype.name = "";	//子类的所有属性和方法要在prototype属性被赋值之后
		ClassB.prototype.sayName = function(){
			alert(this.name);
		};

		//测试
		var objA = new ClassA();
		var objB = new ClassB();
		objA.color = "red";
		objB.color = "blue";
		objB.name = "Nicholas";
		objA.sayColor();
		objB.sayColor();
		objB.sayName();

		//对ClassB的所有实例使用 instanceof 为ClassA和ClassB 都返回true
		alert(objB instanceof ClassA);
		alert(objB instanceof ClassB);
	}
	//5、混合方式,此方法为最好的继承方式
	function extendsmethod5(){
		function ClassA(sColor){
			this.color = sColor;
		}

		ClassA.prototype.sayColor = function(){
			alert(this.color);
		};
		function ClassB(sColor, sName){
			ClassA.call(this, sColor);	//用对象冒充继承ClassA类的sColor属性
			this.name = sName;
		}

		ClassB.prototype = new ClassA();	 //用原型链继承ClassA类的方法
		ClassB.prototype.sayName = function(){
			alert(this.name);
		};

		//测试
		var objA = new ClassA("red");
		var objB = new ClassB("blue", "Nicholas");
		objA.sayColor();
		objB.sayColor();
		objB.sayName();
	}
参考资料:JavaScript高级程序设计
posted @ 2010-10-24 01:09  leetom  阅读(147)  评论(0编辑  收藏  举报