admin管理员组文章数量:1307050
I'm writing a small object-oriented wrapper around a canvas object, and I'd like to set some button callback to actual function members, instead of globally scoped functions (this way I can refer the context object as a member).
function CanvasManager(canvasId) {
this.canvas = document.getElementById(canvasId);
this.ctx = this.canvas.getContext('2d');
var imageLoader = document.getElementById('imageLoader');
imageLoader.addEventListener('change', this.handleImage, false);
var lineNumberField = document.getElementById('linenumber');
lineNumberField.addEventListener('change', this.onLineNumberChange, false);
}
function handleImage = function(e) {
var reader = new FileReader();
var that = this;
reader.onload = function(event){
var img = new Image();
img.onload = function(){
that.canvas.width = img.width;
that.canvas.height = img.height;
that.ctx.drawImage(img,0,0);
};
img.src = event.target.result;
};
reader.readAsDataURL(e.target.files[0]);
};
This is called in an inline script in the html:
<div id="canvas-container" style="display:none;">
<canvas id="imageCanvas"></canvas>
</div>
...
<script lang="javascript">new CanvasManager('imageCanvas');</script>
This doesn't work because in the handleImage
callback, "this" doesn't refer to the CanvasManager
instance, but the imageLoader
instance, to my great confusion.
What am I doing wrong here?
I'm writing a small object-oriented wrapper around a canvas object, and I'd like to set some button callback to actual function members, instead of globally scoped functions (this way I can refer the context object as a member).
function CanvasManager(canvasId) {
this.canvas = document.getElementById(canvasId);
this.ctx = this.canvas.getContext('2d');
var imageLoader = document.getElementById('imageLoader');
imageLoader.addEventListener('change', this.handleImage, false);
var lineNumberField = document.getElementById('linenumber');
lineNumberField.addEventListener('change', this.onLineNumberChange, false);
}
function handleImage = function(e) {
var reader = new FileReader();
var that = this;
reader.onload = function(event){
var img = new Image();
img.onload = function(){
that.canvas.width = img.width;
that.canvas.height = img.height;
that.ctx.drawImage(img,0,0);
};
img.src = event.target.result;
};
reader.readAsDataURL(e.target.files[0]);
};
This is called in an inline script in the html:
<div id="canvas-container" style="display:none;">
<canvas id="imageCanvas"></canvas>
</div>
...
<script lang="javascript">new CanvasManager('imageCanvas');</script>
This doesn't work because in the handleImage
callback, "this" doesn't refer to the CanvasManager
instance, but the imageLoader
instance, to my great confusion.
What am I doing wrong here?
Share Improve this question edited May 9, 2014 at 20:47 Robert 11k16 gold badges75 silver badges119 bronze badges asked May 9, 2014 at 14:57 Fabien Benoit-KochFabien Benoit-Koch 2,8412 gold badges22 silver badges33 bronze badges 3-
What
this
evaluates to generally depends on how the function is being called; but I don't see that in this code. Could you include that section? – Katana314 Commented May 9, 2014 at 14:59 - Ah yes sorry, i'll edit – Fabien Benoit-Koch Commented May 9, 2014 at 15:00
-
1
See
.bind()
. – jfriend00 Commented May 9, 2014 at 15:17
3 Answers
Reset to default 9sorry for the ment - actually, I had misinterepreted the issue as you described it if the issue was inside the second method.
As the others implied, the event listener is going to call the function with window
as the this
object. Don't worry, even as a JS guru I agree it doesn't make a lot of sense.
While you can simply put everything in closures and put this
into a constant var
(ie, me
or self
) my preference is to customize the call to the function to always have a particular this
reference. You can do this like so:
imageLoader.addEventListener('change', this.handleImage.bind(this), false);
bind() is a relatively new JavaScript function that gives you a new method, representing the original, but called with a particular this
context. Some JavaScript libraries have equivalents that are patible with older browsers, like Dojo's "hitch". But, since your code involves a <canvas>
anyway, you should be mostly okay for patibility.
try this
function CanvasManager(canvasId) {
this.canvas = document.getElementById(canvasId);
this.ctx = this.canvas.getContext('2d');
var imageLoader = document.getElementById('imageLoader');
imageLoader.addEventListener('change', this.handleImage, false);
var lineNumberField = document.getElementById('linenumber');
lineNumberField.addEventListener('change', this.onLineNumberChange, false);
var self = this; // keep CanvasManager instance
this.onLineNumberChange = function(){
};
this.handleImage = function(){
console.log(self); // use CanvasManager instance
}
}
It looks like your function handleImage is outside your main function (or class) that you are trying to use. I would update the code as below:
function CanvasManager(canvasId) {
var me = this;
me.canvas = document.getElementById(canvasId);
me.ctx = me.canvas.getContext('2d');
var imageLoader = document.getElementById('imageLoader');
imageLoader.addEventListener('change', me.handleImage, false);
var lineNumberField = document.getElementById('linenumber');
lineNumberField.addEventListener('change', me.onLineNumberChange, false);
me.handleImage = function(e) {
var reader = new FileReader();
reader.onload = function(event){
var img = new Image();
img.onload = function(){
me.canvas.width = img.width;
me.canvas.height = img.height;
me.ctx.drawImage(img, 0, 0);
};
img.src = event.target.result;
};
reader.readAsDataURL(e.target.files[0]);
}
}
By moving the handleImage inside the function it is now in scope of the class. Also by using me = this at the start of the method to always have access to it's class instance as the this will by default reference the objects who's event triggered it.
本文标签: javascriptHow to set an event listener callback to a member functionStack Overflow
版权声明:本文标题:javascript - How to set an event listener callback to a member function - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1741829625a2399854.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论