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

回答了一个为什么类要用prototype,涉及实例化对象的过程和深拷贝,浅拷贝等基础知识,在这分享下,菜鸟看看,欢迎指正
为什么JavaSciript中要用prototype这个东西? 
举个简单例子:
function f1(){ 
   this.method1=function(){
       return 'method1'
   }
}
f1.prototype.method2=function(){return 'method2'}
var obj=new f1()
我理解当js引擎读到new f1()时,其实是先new Object,即实例出了一个Object类的对象,然后这个空对象(其实不是空对象,它里面有一个constructor属性和String属性)原型继承了f1.prototype的一组属性和方法,也可以说是这个空对象深拷贝了f1.prototype所指向的对象,如果你不理解啥叫深拷贝,举个例子比如说m,n是两个对象,
  var m=new Object();
  m.x=10
  m.method1=function(){
    return 'ok'
  }
如果说让n深拷贝m, 不是说让n=m, 这叫浅拷贝,浅拷贝的特点是m把对象在内存堆中的地址拷贝给n,也就是说m和n指向的是同样的对象,当m.x=100时,n.x也变为100,这并不是我希望的,我希望的是n和m是两个对象。那如何深拷贝呢?
方法如下:
var m={};
m.x=1;
m.method=function (){return 123}
var n={};
for(shuxing in m){
   n[shuxing]=m[shuxing]
}
alert(n.x)
alert(n.method)
这时候改变m.x的时候,n.x不会同时发生改变,这就叫深拷贝。
这里有一点必须要清楚:在js中,一个变量类型是由变量的值决定,比如说:
var a=1
它在内存的栈中存的就是a=1
如果var a=function(){ alert('ok') }
那么a在栈中存的是一个地址,这个地址指向的是堆中的function(){ alert('ok') },
理解这个就应该明白上面m.method和n.method存的都是相同的地址,这个地址指向function (){return 123}

回到本文正题:
function f1(){ 
   this.method1=function(){
       return 'method1'
   }
}
f1.prototype.method2=function(){return 'method2'}
每当我实例化一个f1时,this.method1这样的属性都要被创建一次存在堆中,创建10个对象,就要10个这样的function(){return 'method1'}函数实体,而method2这样的原型方法只是复制了10个指向它的地址,而存在堆中的function(){return 'method2'}实体函数始终就一个。
这个哪个效率高,一目了然了吧。
------解决方案--------------------
楼主的理解不对,你所说的var obj = new f1()空对象,其实它里面没有自身的constructor,因为连这个都是f1原型上的,f1.prorotype 类似 {constructor: f1},然后new f1()构造出来的对象访问的constructor是f1.prorotype上的,如果对obj.constructor设置一个新值后才会是它自身的