- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
众所周知,当我们在 javascript 中创建类时,普通函数返回类对象,但事件返回事件对象,类对象丢失
function class(a){
this.name=a;
document.addEventListener('click',this.click,false);
xhr.addEventListener('load',this.xhr,false);
this.normal()
}
class.prototype={
click:function(e){
//e=event,this=theDocument //can't access class
},
xhr:function(e){
//e=event,this=theXHR //can't access class
},
normal:function(e){
//e=null,this=class
}
}
将这些事件绑定(bind)到我们的类的最佳方法是什么?
最好的方式我的意思是没有或只是一个很小的引用,能够以 native 方式删除事件(removeEventListener)并且绝对不会造成内存泄漏。
1.要删除事件监听器,您需要将函数作为引用传递,所以 addEventListener('click',function(){alert('something')},false)
不起作用.
2.我读到像 var that=this
这样的引用在函数内部会产生泄漏,对吗?
已知方法
function class(a){
this.name=a;
var that=this;// reference
//simply reference the whole object as a variable.
var bindedClick=this.click.bind(this);//bind the click to the class
//(js 1.85)
//can i use removeEventListener('click',bindedClick,false) later?
//apply && call (js 1.3)
}
因为我不确定 var that=this
(因为它是整个对象)是否会造成泄漏,有时我会通过将信息保存到数组中并将其作为引用使用 id 来最小化这种情况..
var class={};
var id='ID'+Date.now();
class[id].info={here i store all the info i need later text only}
//this will be stored also in a cookie / Localstorage to reuse later.
class[id].dom={here i store the dom references}
class[id].events{here i store the xhr events}//if needed
//this are Temp only
为了获取信息,我只是通过将 id 添加到事件元素来传递它
class[id].events.xhr.id=id;
class[id].events.xhr.onload=class.f
class.prototype.f=function(e){
//this.response,class[this.id]<- access everything.
this.removeEventListener('load',class.f,false);
delete class[this.id].events.xhr;
delete this.id
}
class[id].dom.id=id;
class[id].dom.onclick=class.f2
class.prototype.f2=function(e){
//class[e.target.id],class[this.id]<- access everything.
this.removeEventListener('click',class.f2,false);
delete class[this.id].dom;
delete this.id
}
正如您在上面的示例中看到的,我可以访问所有内容,而引用只是一个小字符串...
我存储 dom 是因为我在加载时定义了 dom 引用,所以我不必每次都调用 getElementById()
;
我将像 XHR 这样的事件存储在类中,因为我希望能够从外部调用 xhr.abort().. 并且还能够调用 removeEventListener。
我需要尽量减少对内存的影响,但另一方面我需要控制许多具有多个同时发生的事件的元素,以通过删除所有事件和引用来“手动”控制垃圾收集器。
为了确保您了解问题比看起来更严重...:它是 chrome 的下载管理器。下载网址的输入字段:
1.xhr to get the fileinfo (size,name,acceptranges,mime)
2.store info in localstorage and cached array
2.create visual dom elements to show progress (event:progress,click,mouseover..)
3.xhr request a chunk 0-1000(event:load)
4.onprogress display progress data (event:progress,error)
5.request filesystem(event:ok,error)
6.readfile/check file (event:ok,error)
7.request filewriter (event:ok,error)
8.append to file (events=ok,error)
9.on ok start again from 3. until file is finished
10.when finished i delete all the **references / events / extra info**
//this to help the garbage collector.
11.change the dom contents.
每个文件每秒都有太多事件。
这 3 个中哪个是最好的解决方案,或者有更好的解决方案吗?
bind();//or call / apply
var that=this; //reference to the whole object
var id=uniqueid; // reference to the object's id
基于答案:
(function(W){
var D,dls=[];
function init(){
D=W.document;
dls.push(new dl('url1'));
dls.push(new dl('url2'));
}
function dl(a){
this.MyUrl=a;
var that=this;
var btn=D.createElement('button');
btn.addEventListener('click',this.clc,false);
D.body.appendChild(btn);
}
dl.prototype={
clc:function(e){
console.log(that)
}
}
W.addEventListener('load',init,false);
})(window)
var that=this 不起作用。
这行得通...但是我需要大量的检查,swich if 和执行多个函数。
(function(W){
var D,dls=[];
function init(){
D=W.document;
dls.push(new dl('url1'));
dls.push(new dl('url2'));
}
function dl(a){
this.MyUrl=a;
this.btn=D.createElement('button');
btn.addEventListener('click',this,false);
D.body.appendChild(btn);
}
dl.prototype={
handleEvent:function(e){
e.target.removeEventListener('click',this,false);//does this the work?
return this.clc(e);
},
clc:function(e){
console.log(this,e)
}
}
W.addEventListener('load',init,false);
})(window)
绑定(bind):
(function(W){
var D,dls=[];
function init(){
D=W.document;
dls.push(new dl('url1'));
dls.push(new dl('url2'));
}
function dl(a){
this.MyUrl=a;
this.clcB=this.clc.bind(this);
this.btn=D.createElement('button');
this.btn.addEventListener('click',this.clcB,false);
D.body.appendChild(this.btn);
}
dl.prototype={
clc:function(e){
e.target.removeEventListener('click',this.clcB,false);//does this the work?
delete this.clcB;
console.log(this)
}
}
W.addEventListener('load',init,false);
})(window)
最佳答案
更好的解决方案是让您的“类”实现EventListener 接口(interface)。
您可以通过向 MyClass.prototype
添加一个 handleEvent
方法来实现。这允许您将对象直接传递给 .addEventListener()
而不是传递处理程序。
当事件发生时,handleEvent()
方法将被调用,您的对象作为this
值。这使您可以访问对象的所有属性/方法。
function MyClass(a) {
this.name = a;
// pass the object instead of a function
document.addEventListener('click', this, false);
xhr.addEventListener('load', this, false); // where did `xhr` come from?
this.normal()
}
MyClass.prototype = {
// Implement the interface
handleEvent: function(e) {
// `this` is your object
// verify that there's a handler for the event type, and invoke it
return this[e.type] && this[e.type](e);
},
click: function (e) {
// `this` is your object
},
load: function (e) {
// `this` is your object
},
normal: function (e) {
// `this` is your object
}
}
请注意,我将您的 xhr
方法的名称更改为 load
。这使得根据事件类型调用正确的方法变得更加容易。
然后当需要调用 .removeEventListener()
时,就像元素中的正常操作一样,但再次传递对象而不是处理程序。
关于javascript - 将事件函数绑定(bind)到类,但使用 removeEventListener 并删除其引用,从而使垃圾收集器能够正常工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18276516/
C语言sscanf()函数:从字符串中读取指定格式的数据 头文件: ?
最近,我有一个关于工作预评估的问题,即使查询了每个功能的工作原理,我也不知道如何解决。这是一个伪代码。 下面是一个名为foo()的函数,该函数将被传递一个值并返回一个值。如果将以下值传递给foo函数,
CStr 函数 返回表达式,该表达式已被转换为 String 子类型的 Variant。 CStr(expression) expression 参数是任意有效的表达式。 说明 通常,可以
CSng 函数 返回表达式,该表达式已被转换为 Single 子类型的 Variant。 CSng(expression) expression 参数是任意有效的表达式。 说明 通常,可
CreateObject 函数 创建并返回对 Automation 对象的引用。 CreateObject(servername.typename [, location]) 参数 serv
Cos 函数 返回某个角的余弦值。 Cos(number) number 参数可以是任何将某个角表示为弧度的有效数值表达式。 说明 Cos 函数取某个角并返回直角三角形两边的比值。此比值是
CLng 函数 返回表达式,此表达式已被转换为 Long 子类型的 Variant。 CLng(expression) expression 参数是任意有效的表达式。 说明 通常,您可以使
CInt 函数 返回表达式,此表达式已被转换为 Integer 子类型的 Variant。 CInt(expression) expression 参数是任意有效的表达式。 说明 通常,可
Chr 函数 返回与指定的 ANSI 字符代码相对应的字符。 Chr(charcode) charcode 参数是可以标识字符的数字。 说明 从 0 到 31 的数字表示标准的不可打印的
CDbl 函数 返回表达式,此表达式已被转换为 Double 子类型的 Variant。 CDbl(expression) expression 参数是任意有效的表达式。 说明 通常,您可
CDate 函数 返回表达式,此表达式已被转换为 Date 子类型的 Variant。 CDate(date) date 参数是任意有效的日期表达式。 说明 IsDate 函数用于判断 d
CCur 函数 返回表达式,此表达式已被转换为 Currency 子类型的 Variant。 CCur(expression) expression 参数是任意有效的表达式。 说明 通常,
CByte 函数 返回表达式,此表达式已被转换为 Byte 子类型的 Variant。 CByte(expression) expression 参数是任意有效的表达式。 说明 通常,可以
CBool 函数 返回表达式,此表达式已转换为 Boolean 子类型的 Variant。 CBool(expression) expression 是任意有效的表达式。 说明 如果 ex
Atn 函数 返回数值的反正切值。 Atn(number) number 参数可以是任意有效的数值表达式。 说明 Atn 函数计算直角三角形两个边的比值 (number) 并返回对应角的弧
Asc 函数 返回与字符串的第一个字母对应的 ANSI 字符代码。 Asc(string) string 参数是任意有效的字符串表达式。如果 string 参数未包含字符,则将发生运行时错误。
Array 函数 返回包含数组的 Variant。 Array(arglist) arglist 参数是赋给包含在 Variant 中的数组元素的值的列表(用逗号分隔)。如果没有指定此参数,则
Abs 函数 返回数字的绝对值。 Abs(number) number 参数可以是任意有效的数值表达式。如果 number 包含 Null,则返回 Null;如果是未初始化变量,则返回 0。
FormatPercent 函数 返回表达式,此表达式已被格式化为尾随有 % 符号的百分比(乘以 100 )。 FormatPercent(expression[,NumDigitsAfterD
FormatNumber 函数 返回表达式,此表达式已被格式化为数值。 FormatNumber( expression [,NumDigitsAfterDecimal [,Inc
我是一名优秀的程序员,十分优秀!