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>*/ }
jQuery对象的方法是写在prototype里面的,所以是共享的。
本人写的jRaiser是用for…in的方式把指定对象的方法的引用复制到元素,也是共享的。