jQuery实例内存空间占用

2010-2-8

刚接触jquery时很好奇,一个jQuery对象,那么多方法可以用,要是每个对象都保存着这些方法,那得占用多大的内存空间啊。很显然,那些方法都是共用的,只保存一份。今天闲着,研究了下。

要知道哪些方法是每个实例各有一份,哪些方法是共享的,还是先来研究下js的基础:js内部是怎样调用一个实例的属性/方法的。看这段代码:

    var Test = function () {
        this.a = "a";
        this.b = "b";
        this.c = function(){
            return "c";
        }
    }
    Test.prototype = {
        b: "b_prototype",
        d: function(){ return "d"; },
        e: "e"
    }

    var t1 = new Test();
    var t2 = new Test();

var t1 = new Test(),这一句,在 Firefox 下,不考虑参数传递,可以用下面的代码来表示 new 的过程:

var o = {__proto__: Test.prototype};
Test.apply(o);
t1 = o;
//摘自http://lifesinger.org/blog/2009/06/yui3-oop/

经过Test.apply(o);这一句,o = {__proto__: Test.prototype, a: “a”, b: “b”, c: function(){ return “c” } }

调用t1(即o)实例的方法/属性时,会先在o查找是否存在,如果存在,即返回,不存在,则沿着原型链__proto__往上查找,实例对象t1的__proto__指向原型Test.prototype,而Test.prototype.__proto__指向父类的原型,一层层往上搜索,这里Test继承原始天尊Object,所以Test.prototype.__proto__ === Object.prototype

alert(t1.a) //a 在对象中找到a = “a”
alert(t1.b) //b 在对象中找到b = “b”,不再继续查找,忽略对象原型里的b = “b_prototype”
alert(t1.e) //e 在对象中找不到d,沿原型链找到Test.prototype有属性e = “e”

从new语句的分解可以看到,在构造函数里用this.xx = xx生成的方法/属性是每个实例对象都会复制一份的,而prototype里的方法/属性则所有对象共享一份。

alert(t1.c === t2.c) //false t1 t2两个对象的方法c是不同的拷贝,分别保存在t1 t2里
alert(t1.d === t2.d) //true 两个方法d都指向Test.prototype.d

需要注意的是,如果你给t1.d赋了新的值或函数,并不等于修改了Test.prototype.d,这点曾经迷惑了我:

t1.d = “new d”;
alert(t1d === t2.d) //false t2仍然指向Test.prototype.d,而t1在自己对象里新增了属性d,调用t1.d时不会再沿原型链向上查找

回过头看看jQuery,很明显,所有jQuery实例用到的方法都保存在prototype里,只保存一份,jQuery实例对象本身只包含了length selector context三个属性,以及搜索到的DOM。例:

    <div id="tid1" class="tclass"></div>
    <div id="tid2" class="tclass"></div>
    //在jquery源码里jQuery.fn ==  jQuery.fn.init.prototype == jQuery.prototype
    $(".tclass") == {__proto__:jQuery.fn.init.prototype,
                      selector: ".tclass",
                      context: document,
                      length: 2,
                      0:/*指向DOM元素<div id="tid1" class="tclass"></div>*/,
                      1:/*指向DOM元素<div id="tid2" class="tclass"></div>*/
                     }
评论

2010年2月10日 9:04

jQuery对象的方法是写在prototype里面的,所以是共享的。
本人写的jRaiser是用for…in的方式把指定对象的方法的引用复制到元素,也是共享的。

2010年3月12日 1:06

我这里也有几段类似的代码,挺有趣的:
http://docs.google.com/View?id=afqcbsf26d3_450grd597gp