对象中的 AddEventListener
AddEventListener with in a object
我可能需要你的帮助,目前我正在尝试通过 addEventListener 激活来调用对象内的方法。问题是一旦调用该方法,this 指针就会发生变化。我尝试使用 .call 为方法返回正确的上下文,它按预期工作,但这是最好的方法吗?
<!doctype html>
<html>
<head>
<title>Java Script Test</title>
<meta charset="UTF-8" />
<!-- <script src="//code.jquery.com/jquery-1.11.2.min.js"></script> -->
<script src="../resurces/js/jquery-1.11.2.min.js" ></script>
<script>
var test_class = function(){
this.variable = "more text";
this.click = function(){
$("#return").text("Content: "+this.variable);
}
this.aktivate_listener = function(){
var that = this;
document.getElementById("clicker").addEventListener("click", function(){that.click.call(that)});
}
}
$("document").ready(function(){
console.log("#ready");
var class1 = new test_class();
class1.aktivate_listener();
});
</script>
</head>
<body>
<p id="clicker">This is some Text to click on.</p>
<p id="return"></p>
</body>
</html>
你们中有人知道更好的方法吗?
感谢您的努力,
弗洛
基本上没问题,但有几点:
您无需执行 that.click.call(that)
- 只需 that.click()
即可。
您没有传递匿名函数接收的事件对象。如果你不需要它,那很好,但我想我会提到它。
另一种选择是使用 Function#bind
:
this.aktivate_listener = function(){
document.getElementById("clicker").addEventListener("click", this.click.bind(this));
}
Function#bind
returns 一个函数,当被调用时,返回并调用原始函数 this
设置为特定值。因此 this.click.bind(this)
创建了一个函数,当调用该函数时,将在对象上调用 click
,this
引用该对象。绑定函数的任何参数都会在调用基础函数时传递。
回复您的评论:
But I read that you can't remove an EventListener that is created with .bind A problem in the example above is that you cannot remove the listener with bind
. That is taken from the Mozilla Developer Network.
如果是这样,MDN 是错误的。它是社区编辑的,发生了。 :-)
就能够使用 removeEventListener
删除处理程序而言,您的代码与使用上述 Function#bind
完全没有区别 :您如果不更改代码以记住我们传递给 addEventListener
.
的内容,则无法在任何一种情况下删除侦听器
使用 bind
的事件处理程序没有什么特别之处。就像任何其他事件处理程序一样,如果你想用 removeEventListener
删除它,你必须引用你在删除它时添加的 相同的函数 。在您的代码中,这将是您包裹在 that.click.call(that);
周围的匿名函数,并且由于您没有保留对它的引用,所以您无法删除它。同样,在我上面的代码中,您不能删除侦听器,因为我没有保留对绑定函数的引用。
如果这是您需要做的事情,请记住您要删除的函数——这是对您的匿名函数的引用,或者是对 Function#bind
返回函数的引用。例如,您可以将它存储在您的对象上。
this.aktivate_listener = function(){
if (this.boundClick) {
this.deaktivate_listener();
}
this.boundClick = this.click.bind(this);
document.getElementById("clicker").addEventListener("click", this.boundClick);
};
this.deacktivate_listener = function(){
document.getElementById("clicker").removeEventListener("click", this.boundClick);
this.boundClick = null;
};
再次查看您的代码,您有第三种选择:您的 click
函数是对创建实例的 test_class
调用的闭包,因此您不需要创建另一个闭包,只用你已有的:
var test_class = function(){
// Remember `this` in a variable
var self = this;
this.variable = "more text";
this.click = function(){
// Use it here
$("#return").text("Content: "+self.variable);
};
this.aktivate_listener = function(){
// Just use `this.click` here
document.getElementById("clicker").addEventListener("click", this.click);
};
this.deaktivate_listener = function(){
// Just use `this.click` here
document.getElementById("clicker").removeEventListener("click", this.click);
};
};
旁注:您需要在 var f = function() { };
等语句末尾添加 ;
,因为它们是语句,而不是声明。我已经在上面添加了它们。如果您不提供,大多数时候自动分号插入会为您添加,但如果您不小心,可能会出错。
以上所有的例子:
你的方式没有 .call
(没有 deaktivate):
var Test = function(id, name) {
this.id = id;
this.name = name;
this.click = function() {
snippet.log("My name is " + this.name);
};
this.aktivate_listener = function() {
var that = this;
document.getElementById(this.id).addEventListener(
"click",
function() { that.click(); },
false
);
};
};
var t1 = new Test("one", "test one");
t1.aktivate_listener();
var t2 = new Test("two", "test two");
t2.aktivate_listener();
<div id="one">Click me (one)</div>
<div id="two">Click me (two)</div>
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
使用 Function#bind
(没有去激活):
var Test = function(id, name) {
this.id = id;
this.name = name;
this.click = function() {
snippet.log("My name is " + this.name);
};
this.aktivate_listener = function() {
document.getElementById(this.id).addEventListener(
"click",
this.click.bind(this),
false
);
};
};
var t1 = new Test("one", "test one");
t1.aktivate_listener();
var t2 = new Test("two", "test two");
t2.aktivate_listener();
<div id="one">Click me (one)</div>
<div id="two">Click me (two)</div>
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
使用现有的闭包(没有 deaktivate):
var Test = function(id, name) {
var self = this;
this.id = id;
this.name = name;
this.click = function() {
snippet.log("My name is " + self.name);
};
this.aktivate_listener = function() {
document.getElementById(this.id).addEventListener(
"click",
this.click,
false
);
};
};
var t1 = new Test("one", "test one");
t1.aktivate_listener();
var t2 = new Test("two", "test two");
t2.aktivate_listener();
<div id="one">Click me (one)</div>
<div id="two">Click me (two)</div>
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
你的方式没有 .call
(有 deaktivate):
var Test = function(id, name) {
this.id = id;
this.name = name;
this.counter = 0;
this.click = function() {
snippet.log("My name is " + this.name);
if (++this.counter == 2) {
this.deaktivate_listener();
};
};
this.aktivate_listener = function() {
var that = this;
if (this.boundClick) {
this.deaktivate_listener();
}
this.boundClick = function() { that.click(); };
document.getElementById(this.id).addEventListener(
"click",
this.boundClick,
false
);
};
this.deaktivate_listener = function() {
if (this.boundClick) {
document.getElementById(this.id).removeEventListener(
"click",
this.boundClick,
false
);
this.boundClick = null;
}
};
};
var t1 = new Test("one", "test one");
t1.aktivate_listener();
var t2 = new Test("two", "test two");
t2.aktivate_listener();
<div id="one">Click me (one) (second click deactivates)</div>
<div id="two">Click me (two) (second click deactivates)</div>
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
使用 Function#bind
(使用 deaktivate):
var Test = function(id, name) {
this.id = id;
this.name = name;
this.counter = 0;
this.click = function() {
snippet.log("My name is " + this.name);
if (++this.counter == 2) {
this.deaktivate_listener();
};
};
this.aktivate_listener = function() {
if (this.boundClick) {
this.deaktivate_listener();
}
this.boundClick = this.click.bind(this);
document.getElementById(this.id).addEventListener(
"click",
this.boundClick,
false
);
};
this.deaktivate_listener = function() {
if (this.boundClick) {
document.getElementById(this.id).removeEventListener(
"click",
this.boundClick,
false
);
this.boundClick = null;
}
};
};
var t1 = new Test("one", "test one");
t1.aktivate_listener();
var t2 = new Test("two", "test two");
t2.aktivate_listener();
<div id="one">Click me (one) (second click deactivates)</div>
<div id="two">Click me (two) (second click deactivates)</div>
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
使用现有闭包(带 deaktivate):
var Test = function(id, name) {
var self = this;
this.id = id;
this.name = name;
this.counter = 0;
this.click = function() {
snippet.log("My name is " + self.name);
if (++self.counter == 2) {
self.deaktivate_listener();
};
};
this.aktivate_listener = function() {
document.getElementById(this.id).addEventListener(
"click",
this.click,
false
);
};
this.deaktivate_listener = function() {
document.getElementById(this.id).removeEventListener(
"click",
this.click,
false
);
};
};
var t1 = new Test("one", "test one");
t1.aktivate_listener();
var t2 = new Test("two", "test two");
t2.aktivate_listener();
<div id="one">Click me (one) (second click deactivates)</div>
<div id="two">Click me (two) (second click deactivates)</div>
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
这是我目前使用的版本,由@T.J制作而成。克劳德回答。
function boxOperator(){
this.event = [];
this.addEvent = function(element, event, tocall_function, arg){
var call_function = tocall_function.bind(this, arg);
this.event[this.event.length] = {
"element" : element,
"event" : event,
"call_function" : call_function
};
document.getElementById(element).addEventListener(event,call_function);
};
this.removeEvent = function(element, event){
if(!element){return false;};
var remove_entry = function(index, array){return array.slice(0,index-1).concat(array.slice(index+1));}
for(var i = 0; i < this.event.length;i++){
if(this.event[i].element == element){
var entry = this.event[i];
if(entry.event == event){
document.getElementById(entry.element).removeEventListener(entry.event,entry.call_function);
this.event = remove_entry(i, this.event);
}
if(typeof event == "undefined"){
document.getElementById(entry.element).removeEventListener(entry.event,entry.call_function);
this.event = remove_entry(i, this.event);
}
}
}
};
}
我可能需要你的帮助,目前我正在尝试通过 addEventListener 激活来调用对象内的方法。问题是一旦调用该方法,this 指针就会发生变化。我尝试使用 .call 为方法返回正确的上下文,它按预期工作,但这是最好的方法吗?
<!doctype html>
<html>
<head>
<title>Java Script Test</title>
<meta charset="UTF-8" />
<!-- <script src="//code.jquery.com/jquery-1.11.2.min.js"></script> -->
<script src="../resurces/js/jquery-1.11.2.min.js" ></script>
<script>
var test_class = function(){
this.variable = "more text";
this.click = function(){
$("#return").text("Content: "+this.variable);
}
this.aktivate_listener = function(){
var that = this;
document.getElementById("clicker").addEventListener("click", function(){that.click.call(that)});
}
}
$("document").ready(function(){
console.log("#ready");
var class1 = new test_class();
class1.aktivate_listener();
});
</script>
</head>
<body>
<p id="clicker">This is some Text to click on.</p>
<p id="return"></p>
</body>
</html>
你们中有人知道更好的方法吗?
感谢您的努力, 弗洛
基本上没问题,但有几点:
您无需执行
that.click.call(that)
- 只需that.click()
即可。您没有传递匿名函数接收的事件对象。如果你不需要它,那很好,但我想我会提到它。
另一种选择是使用 Function#bind
:
this.aktivate_listener = function(){
document.getElementById("clicker").addEventListener("click", this.click.bind(this));
}
Function#bind
returns 一个函数,当被调用时,返回并调用原始函数 this
设置为特定值。因此 this.click.bind(this)
创建了一个函数,当调用该函数时,将在对象上调用 click
,this
引用该对象。绑定函数的任何参数都会在调用基础函数时传递。
回复您的评论:
But I read that you can't remove an EventListener that is created with .bind
A problem in the example above is that you cannot remove the listener with bind
. That is taken from the Mozilla Developer Network.
如果是这样,MDN 是错误的。它是社区编辑的,发生了。 :-)
就能够使用 removeEventListener
删除处理程序而言,您的代码与使用上述 Function#bind
完全没有区别 :您如果不更改代码以记住我们传递给 addEventListener
.
使用 bind
的事件处理程序没有什么特别之处。就像任何其他事件处理程序一样,如果你想用 removeEventListener
删除它,你必须引用你在删除它时添加的 相同的函数 。在您的代码中,这将是您包裹在 that.click.call(that);
周围的匿名函数,并且由于您没有保留对它的引用,所以您无法删除它。同样,在我上面的代码中,您不能删除侦听器,因为我没有保留对绑定函数的引用。
如果这是您需要做的事情,请记住您要删除的函数——这是对您的匿名函数的引用,或者是对 Function#bind
返回函数的引用。例如,您可以将它存储在您的对象上。
this.aktivate_listener = function(){
if (this.boundClick) {
this.deaktivate_listener();
}
this.boundClick = this.click.bind(this);
document.getElementById("clicker").addEventListener("click", this.boundClick);
};
this.deacktivate_listener = function(){
document.getElementById("clicker").removeEventListener("click", this.boundClick);
this.boundClick = null;
};
再次查看您的代码,您有第三种选择:您的 click
函数是对创建实例的 test_class
调用的闭包,因此您不需要创建另一个闭包,只用你已有的:
var test_class = function(){
// Remember `this` in a variable
var self = this;
this.variable = "more text";
this.click = function(){
// Use it here
$("#return").text("Content: "+self.variable);
};
this.aktivate_listener = function(){
// Just use `this.click` here
document.getElementById("clicker").addEventListener("click", this.click);
};
this.deaktivate_listener = function(){
// Just use `this.click` here
document.getElementById("clicker").removeEventListener("click", this.click);
};
};
旁注:您需要在 var f = function() { };
等语句末尾添加 ;
,因为它们是语句,而不是声明。我已经在上面添加了它们。如果您不提供,大多数时候自动分号插入会为您添加,但如果您不小心,可能会出错。
以上所有的例子:
你的方式没有 .call
(没有 deaktivate):
var Test = function(id, name) {
this.id = id;
this.name = name;
this.click = function() {
snippet.log("My name is " + this.name);
};
this.aktivate_listener = function() {
var that = this;
document.getElementById(this.id).addEventListener(
"click",
function() { that.click(); },
false
);
};
};
var t1 = new Test("one", "test one");
t1.aktivate_listener();
var t2 = new Test("two", "test two");
t2.aktivate_listener();
<div id="one">Click me (one)</div>
<div id="two">Click me (two)</div>
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
使用 Function#bind
(没有去激活):
var Test = function(id, name) {
this.id = id;
this.name = name;
this.click = function() {
snippet.log("My name is " + this.name);
};
this.aktivate_listener = function() {
document.getElementById(this.id).addEventListener(
"click",
this.click.bind(this),
false
);
};
};
var t1 = new Test("one", "test one");
t1.aktivate_listener();
var t2 = new Test("two", "test two");
t2.aktivate_listener();
<div id="one">Click me (one)</div>
<div id="two">Click me (two)</div>
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
使用现有的闭包(没有 deaktivate):
var Test = function(id, name) {
var self = this;
this.id = id;
this.name = name;
this.click = function() {
snippet.log("My name is " + self.name);
};
this.aktivate_listener = function() {
document.getElementById(this.id).addEventListener(
"click",
this.click,
false
);
};
};
var t1 = new Test("one", "test one");
t1.aktivate_listener();
var t2 = new Test("two", "test two");
t2.aktivate_listener();
<div id="one">Click me (one)</div>
<div id="two">Click me (two)</div>
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
你的方式没有 .call
(有 deaktivate):
var Test = function(id, name) {
this.id = id;
this.name = name;
this.counter = 0;
this.click = function() {
snippet.log("My name is " + this.name);
if (++this.counter == 2) {
this.deaktivate_listener();
};
};
this.aktivate_listener = function() {
var that = this;
if (this.boundClick) {
this.deaktivate_listener();
}
this.boundClick = function() { that.click(); };
document.getElementById(this.id).addEventListener(
"click",
this.boundClick,
false
);
};
this.deaktivate_listener = function() {
if (this.boundClick) {
document.getElementById(this.id).removeEventListener(
"click",
this.boundClick,
false
);
this.boundClick = null;
}
};
};
var t1 = new Test("one", "test one");
t1.aktivate_listener();
var t2 = new Test("two", "test two");
t2.aktivate_listener();
<div id="one">Click me (one) (second click deactivates)</div>
<div id="two">Click me (two) (second click deactivates)</div>
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
使用 Function#bind
(使用 deaktivate):
var Test = function(id, name) {
this.id = id;
this.name = name;
this.counter = 0;
this.click = function() {
snippet.log("My name is " + this.name);
if (++this.counter == 2) {
this.deaktivate_listener();
};
};
this.aktivate_listener = function() {
if (this.boundClick) {
this.deaktivate_listener();
}
this.boundClick = this.click.bind(this);
document.getElementById(this.id).addEventListener(
"click",
this.boundClick,
false
);
};
this.deaktivate_listener = function() {
if (this.boundClick) {
document.getElementById(this.id).removeEventListener(
"click",
this.boundClick,
false
);
this.boundClick = null;
}
};
};
var t1 = new Test("one", "test one");
t1.aktivate_listener();
var t2 = new Test("two", "test two");
t2.aktivate_listener();
<div id="one">Click me (one) (second click deactivates)</div>
<div id="two">Click me (two) (second click deactivates)</div>
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
使用现有闭包(带 deaktivate):
var Test = function(id, name) {
var self = this;
this.id = id;
this.name = name;
this.counter = 0;
this.click = function() {
snippet.log("My name is " + self.name);
if (++self.counter == 2) {
self.deaktivate_listener();
};
};
this.aktivate_listener = function() {
document.getElementById(this.id).addEventListener(
"click",
this.click,
false
);
};
this.deaktivate_listener = function() {
document.getElementById(this.id).removeEventListener(
"click",
this.click,
false
);
};
};
var t1 = new Test("one", "test one");
t1.aktivate_listener();
var t2 = new Test("two", "test two");
t2.aktivate_listener();
<div id="one">Click me (one) (second click deactivates)</div>
<div id="two">Click me (two) (second click deactivates)</div>
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
这是我目前使用的版本,由@T.J制作而成。克劳德回答。
function boxOperator(){
this.event = [];
this.addEvent = function(element, event, tocall_function, arg){
var call_function = tocall_function.bind(this, arg);
this.event[this.event.length] = {
"element" : element,
"event" : event,
"call_function" : call_function
};
document.getElementById(element).addEventListener(event,call_function);
};
this.removeEvent = function(element, event){
if(!element){return false;};
var remove_entry = function(index, array){return array.slice(0,index-1).concat(array.slice(index+1));}
for(var i = 0; i < this.event.length;i++){
if(this.event[i].element == element){
var entry = this.event[i];
if(entry.event == event){
document.getElementById(entry.element).removeEventListener(entry.event,entry.call_function);
this.event = remove_entry(i, this.event);
}
if(typeof event == "undefined"){
document.getElementById(entry.element).removeEventListener(entry.event,entry.call_function);
this.event = remove_entry(i, this.event);
}
}
}
};
}