我在canvas对象周围编写一个面向对象的小包装器,我想设置一些按钮回调到实际的函数成员,而不是全局范围的函数(这样我可以参考上下文对象作为成员)。
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]);
};
这在html中的内联脚本中调用:
<div id="canvas-container" style="display:none;">
<canvas id="imageCanvas"></canvas>
</div>
...
<script lang="javascript">new CanvasManager('imageCanvas');</script>
这不起作用,因为在handleImage
回调中,&#34;此&#34;我并没有引用CanvasManager
实例,而是引用imageLoader
实例。
我在这里做错了什么?
答案 0 :(得分:4)
对不起评论 - 实际上,如果问题出在第二种方法中,我就误解了这个问题。
正如其他人暗示的那样,事件监听器将使用window
作为this
对象调用该函数。别担心,即使作为一名JS大师,我也同意它没有多大意义。
虽然您可以简单地将所有内容放入闭包中并将this
放入常量var
(即me
或self
),但我的偏好是自定义调用函数始终具有特定的this
引用。你可以这样做:
imageLoader.addEventListener('change', this.handleImage.bind(this), false);
bind()是一个相对较新的JavaScript函数,它为您提供一个新方法,表示原始方法,但使用特定的this
上下文调用。一些JavaScript库具有与旧版浏览器兼容的等价物,例如Dojo的“hitch”。但是,由于您的代码无论如何都涉及<canvas>
,因此您应该完全可以兼容。
答案 1 :(得分:2)
试试这个
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
}
}
答案 2 :(得分:1)
看起来您的函数handleImage不在您尝试使用的主函数(或类)之外。我会更新代码如下:
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]);
}
}
通过在函数内部移动handleImage,它现在在类的范围内。另外通过在方法的开头使用me = this来始终可以访问它的类实例,因为这将默认引用事件触发它的对象。