日期:2014-05-16  浏览次数:20311 次

JS prototype 理解
JS里的对象在Ajax发展之后, 就跟着疯狂起来, 要玩好JS的对象, 就要搞清楚构造器(constructor), 指针(pointer), 原型(prototype)

这篇文章主要记录我对prototype的理解

prototype

最初的用法是, 为了避免方法在构造器里随机数据被实例化时而产生重复的副本
后来被用在"继承"上面了, 注意, JS语义上是没有继承的, 这里说的是人为的实现

总结, prototype其实也是指针, 默认是实例的指针, 当然也可以人为的改变,

父类A, 子类B

默认情况, B.prototype=A.prototype
这样, B可以访问A的所有原型方法, 这时, B的构造器也变成A了

改变一下, B.prototype=A
这样, B可以访问A的所有静态方法, 这时, B的构造器也变成类A的指针->类的指针->Function的指针->Function的构造器

以下是实例验证

	function demo(){
		var A=function(name){
			this.name=name;
		}
		A.prototype.showName=function(){alert(this.name);}
		var B=function(name, age){
			A.call(this, name);
			this.age=age;
		}
		//B.prototype=new A();    //这里2行代码的效果是一样的
		B.prototype=A.prototype;  //目的是返回A的"实例"的指针

		B.prototype.showAge=function(){alert(this.age);}
		var b=new B("david", 31);
		b.showName();
		b.showAge();
	}


严重注意以上代码的备注, 是new之后的instance的指针, 不是Class的指针,
下面改一下代码验证一下

	var A=function(name){
		this.name=name;
		//return this; 这是隐式代码, JS会自动帮我们执行, 这里是关键
	}

改为

	var A=function(name){
		var o=new Object();
		o.name=name;
		return o;
	}

然后, 当执行到b.showName();时, 就会抛出异常了, 因为 showName是prototype方法, 是指定在A的实例指针下的, 给A添加方法pointer()以获取实例的指针, 然后把它赋予B.prototype

	function demo(){
		var A=function(name){
			this.name=name;
		}
		A.prototype.showName=function(){alert(this.name);} //the function return this, "this" is the pointer of instance
		A.prototype.pointer=function(){return this;}
		var B=function(name, age){
			A.call(this, name);
			this.age=age;
		}
		//B.prototype=new A();
		//B.prototype=A.prototype;
		B.prototype=new A().pointer();

		B.prototype.showAge=function(){alert(this.age);}
		var b=new B("david", 31);
		b.showName();
		b.showAge();
	}


以上代码运行正常, 证明了prototype实质上就是指于实例的指针
那么, 如果, 把prototype的指针指于类, 又会如何呢, 我的想法是, 会得到类的静态方法或属性

以下代码, 给A添加静态方法showSex和静态属性city, 然后把A的类,
结果应该是A的原型方法showName会报错, 而b.showSex和alert(b.city)会得到正确的执行

	function demo(){
		var A=function(name){
			this.name=name;
		}
		A.prototype.showName=function(){alert(this.name);} //the function return this, "this" is the pointer of instance
		A.prototype.pointer=function(){return this;}
		A.showSex=function(){alert("male");}
		A.city="shenzhen";

		var B=function(name, age){
			A.call(this, name);
			this.age=age;
		}
		//B.prototype=new A();
		//B.prototype=A.prototype;
		B.prototype=A;

		B.prototype.showAge=function(){alert(this.age);}
		var b=new B("david", 31);
		try {
			b.showName();
		} catch (exception) {
			alert(exception);
		}
		b.showAge();
		b.showSex();
		alert(b.city);
	}


代码执行正常, 验证无误

再检验一下constructor

function demo(){
		var A=function(name){
			this.name=name;
		}
		A.prototype.showName=function(){alert(this.name);} //the function return this, "this" is the pointer of instance
		A.prototype.showSex=function(){alert("male");}
		A.prototype.city="shenzhen";

		var B=function(name, age){
			A.call(this, name);
			this.age=age;
		}
		B.prototype=A.prototype;
		B.prototype.showAge=function(){alert(this.age);}
		var b=new B("david", 31);
		try {
			alert(b.constructor);	//output Class A construct
			alert(b.constructor==A);//output true
		} catch (exception) {
			alert(exception);
		}
	}


结果表明
alert(b.constructor), 连 B 的构造器都变成 A 的了
alert(b.constructor==A), 再比较一次, 输出true, 没有悬念了

继续挖掘, 把B.prototype=A, 即把A的类指针赋予B的prototype

function demo(){
		var A=function(name){
			this.name=name;
		}
		A.prototype.showName=function(){alert(this.name);} //the function return this, "this" is the pointer of instance
		A.prototype.showSex=function(){alert("male");}
		A.prototype.city