欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費電子書(shū)等14項超值服

開(kāi)通VIP
Leak Free Javascript Closures

Leak Free Javascript Closures

October 20, 2005

Javascript closures can be a powerful programming technique. Unfortunately in Internet Explorer they are a common source of memory leaks. Therefore I propose a method to create closures that don‘t leak memory.

Problem

First start with a short explanation of the problem I tried to fix. Here is an example of a simple event handler (IE only for clarity):

function attach(){var element = document.getElementById("my-element");element.attachEvent("onclick", function(){ alert("Clicked: " + element.innerHTML); });}

This seems harmless enough, but the function (closure) is created in a scope which contains element. Since we attach the function to element, a circular reference is created and IE no longer can garbage collect element. This can easily be demonstrated by adding a large string to element.

There are a lot of solutions for this problem, of which most focus on event attaching. But this problem can also occur when Javascript objects are set as a property on an HTML element.

Solution

So we need a function that can access an HTML element without creating an inline closure that leaks memory.

The following code adds a closure method to each function. closure wraps the original function in such a way that this is set to the given object.

Function.prototype.closure = function(obj){// Init object storage.if (!window.__objs)window.__objs = [];// Init closure storage.if (!this.__closureFuncs)this.__closureFuncs = [];// Make sure the object has an id and is stored in the object store.var objId = obj.__closureObjId;if (!objId)__objs[objId = obj.__closureObjId = __objs.length] = obj;// See if we previously created a closure for this object/function pair.var closureFunc = this.__closureFuncs[objId];if (closureFunc)return closureFunc;// Clear reference to keep the object out of the closure scope.obj = null;// Create the closure, store in cache and return result.var me = this;return this.__closureFuncs[objId] = function(){return me.apply(__objs[objId], arguments);};};

So now we can do:

function attach(){var element = document.getElementById("my-element");element.attachEvent("onclick", clickHandler.closure(element));}function clickHandler(){alert("Clicked: " + this.innerHTML);}

Which doesn‘t leak. And can also be used to run any function in a given context:

function myObject(){this.status = "waiting";setTimeout(this.delayedCode.closure(this), 1000);}myObject.prototype ={delayedCode: function(){this.status = "done waiting";}};var o = new myObject();

Some might argue that this fixes one leak with another since all closure context objects are stored in an array. Though this array will be freed on reload, it will stay in memory as long as the user stays on the page.

A simulation of a highly dynamic webpage shows that this isn‘t a big problem in practise. This shows that an html element takes about 1KB and even an application like Xopus doesn‘t create more than 10000 elements in a single session. And even if it would, it would only take about 10MB which I think is acceptable.

Update: new version with less prerequisites

The above mentioned closure function will only work if the original function does not have a (indirect) reference to the object to which the closure is attached. So this will still leak:

function attach(){function clickHandler(){alert("Clicked: " + this.innerHTML);}var element = document.getElementById("my-element");element.attachEvent("onclick", clickHandler.closure(element));}

This is caused by the fact that the created closure function still has a reference to it‘s original function (me). A new version of the closure function fixes that problem:

Function.prototype.closure = function(obj){// Init object storage.if (!window.__objs){window.__objs = [];window.__funs = [];}// For symmetry and clarity.var fun = this;// Make sure the object has an id and is stored in the object store.var objId = obj.__objId;if (!objId)__objs[objId = obj.__objId = __objs.length] = obj;// Make sure the function has an id and is stored in the function store.var funId = fun.__funId;if (!funId)__funs[funId = fun.__funId = __funs.length] = fun;// Init closure storage.if (!obj.__closures)obj.__closures = [];// See if we previously created a closure for this object/function pair.var closure = obj.__closures[funId];if (closure)return closure;// Clear references to keep them out of the closure scope.obj = null;fun = null;// Create the closure, store in cache and return result.return __objs[objId].__closures[funId] = function (){return __funs[funId].apply(__objs[objId], arguments);};};

We can now use the common pattern of creating event handlers inline:

function attach(){var element = document.getElementById("my-element");element.attachEvent("onclick", function(){alert("Clicked: " + this.innerHTML);}.closure(element));}

So now we have truly leak free closures.

In addition we can also easily remove an object from the global array. The following code allows the garbage collector to free an object if there are no other references to it:

window.__objs[obj.__objId] = null;
本站僅提供存儲服務(wù),所有內容均由用戶(hù)發(fā)布,如發(fā)現有害或侵權內容,請點(diǎn)擊舉報。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
+ JavaScript の質(zhì)問(wèn)用スレッド vol.76 + | Rちゃんねる
判斷事件是不是發(fā)生在某組件中的 JS 函數 - BeanSoft‘s Java Blog ...
js倒計時(shí)刷新
vc++訪(fǎng)問(wèn)javascript(2)
Javascript開(kāi)發(fā)經(jīng)驗談(轉)
js筆記合集
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導長(cháng)圖 關(guān)注 下載文章
綁定賬號成功
后續可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服

欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久