Javascript 可以使用多个闭包向函数';什么样的范围可以简化?
我试图将两个变量传递给Javascript 可以使用多个闭包向函数';什么样的范围可以简化?,javascript,Javascript,我试图将两个变量传递给filereader回调。本质上,我是在文件上循环并显示它们的缩略图;要实现这一点,我需要两个变量(在本例中,parent和canvas)。下面的代码是有效的,但我想确保我未来的自己不会恨我现在的自己 我假设在不覆盖this的情况下将两个变量传递到回调函数的作用域是一种相当常见的情况 这段代码使用了一个名称空间(父级),这是可以避免的,但我仍然想知道如何将两个变量传递到回调函数中 reader.onload = (function (parent) { // even fu
filereader
回调。本质上,我是在文件上循环并显示它们的缩略图;要实现这一点,我需要两个变量(在本例中,parent
和canvas
)。下面的代码是有效的,但我想确保我未来的自己不会恨我现在的自己
我假设在不覆盖this
的情况下将两个变量传递到回调函数的作用域是一种相当常见的情况
这段代码使用了一个名称空间(父级),这是可以避免的,但我仍然想知道如何将两个变量传递到回调函数中
reader.onload = (function (parent) { // even funkier closure to access the parent, the canvas, and the file
return function(canvas) { // funky closure to be able access the canvas and file
return function(r) {
canvas.sourceImage.src = r.target.result;
parent.functions.render(canvas);
parent.functions.preview(canvas, canvas.sourceImage.width/10, canvas.sourceImage.height/10);
};
}(parent.canvases[j]);
})(parent);
reader.readAsDataURL(file);
根据注释,这里是完整的代码。我不是特别想要代码审查(
有一个堆栈!
),但是任何反馈都是非常感谢的
(function () {
this.readFiles = function (parent) {
var files = parent.fileInput.files;
var j = parent.canvases.length; // so we don't overwrite old previews
for (var i = 0; i < files.length; i++, j++) {
var file = files[i];
var reader = new FileReader;
var canvas = document.createElement('canvas');
canvas.id = "previewCanvas" + j;
canvas.className = parent.canvasClasses;
canvas.width = 100;
canvas.height = 100;
parent.previewWrapper.appendChild(canvas);
/* Initialize Canvases for each file */
parent.canvases[j] = this.create(document.getElementById('previewCanvas' + j));
reader.onload = (function (parent) { // even funkier closure to access the parent, the canvas, and the file
return function(canvas) { // funky closure to be able access the file
return function(r) {
canvas.sourceImage.src = r.target.result;
parent.functions.render(canvas);
parent.functions.preview(canvas, canvas.sourceImage.width/10, canvas.sourceImage.height/10);
};
}(parent.canvases[j]);
})(parent);
reader.readAsDataURL(file);
}
}
}).apply(Canvas.functions);
(函数(){
this.readFiles=函数(父级){
var files=parent.fileInput.files;
var j=parent.canvases.length;//因此我们不会覆盖旧的预览
对于(var i=0;i
基本上,您可以去掉大部分闭包和其他一些代码
这应该行得通,除非我引入了任何bug。。。您注意到的两个bug现在已修复,感谢您捕获它们!:-)
请注意:
您不需要将Canvas.functions
转换为this
的最外层生命。直接使用Canvas.functions
。这也消除了这个在回调中不正确的可能性(这似乎不是问题,但它有助于保持简单)
您不需要j
变量parent.canvases.length始终与j
的值相同
如果使用.forEach()
而不是for
循环,则会对.forEach()
回调中声明的所有局部变量进行闭包。这真的是你唯一需要的结束
正如您所指出的,像FileReader
这样的“类似数组”的对象可能没有.forEach()
方法。有几种方法可以解决这个问题。一种是为
循环编写一个普通的,并在其中调用一个函数,例如
var files = parent.fileInput.files;
for( var i = 0; i < files.length; i++ ) {
doFile( files[i] );
}
function doFile( file ) {
...
}
var files=parent.fileInput.files;
对于(var i=0;i
这可以通过内联函数expresion来实现,但我喜欢使用单独的命名函数语句来实现这一点——它看起来更清晰一些。(这里的一个警告是,如果
或
for
块,则不要将函数语句本身放在嵌套块中,如——浏览器不能一致地处理它——它需要直接放在外部函数中
reader.onload = (function (parent) { // even funkier closure to access the parent, the canvas, and the file
return function(canvas) { // funky closure to be able access the canvas and file
return function(r) {
canvas.sourceImage.src = r.target.result;
parent.functions.render(canvas);
parent.functions.preview(canvas, canvas.sourceImage.width/10, canvas.sourceImage.height/10);
};
}(parent.canvases[j]);
})(parent);
reader.readAsDataURL(file);
或者,使用Array.prototype.forEach.call()
让您在类似数组的对象上使用forEach
。我在上面更新的代码中使用了这种方法,定义了一个独立的forEach()
函数。您可以将Array.prototype.forEach.call()放入
直接内联,但我认为将其封装在函数中更为简洁。当然,如果您使用的是下划线或LoDash之类的库,则可以使用方便的迭代器,如。.each()
不需要使用document.getElementById()
来获取对当前画布的引用,因为在canvas
变量中已经有了它
在onload()
回调函数中,您不需要任何一个嵌套闭包。该函数已经可以访问必要的变量
代码似乎将名称canvas
用于两种截然不同的内容。第一种是在顶部创建的实际canvas
元素,第二种是canvas.functions.create(canvas)的返回值
。为了避免混淆,我将第二个名称重命名为fileCanvas
。您可能会想出一个更好的名称,只是不要称它为canvas
在onload
回调中,r.target
是与reader
相同的对象,因此您可以直接使用它。如果您确实在这样的事件处理程序中使用参数,我建议将其称为event
(或者e
,如果您需要一个简短的名称)因为这是更常见的。尽管@MichaelGeary主要通过重构代码来回答我的问题,但标题问题的答案是外部函数立即执行,并且可以访问当前变量:
reader.onload = (function (parent) {
var canvas = parent.canvases[j];
// put more variables ad nauseum here.
// They will be passed to the return function without being changed.
return function(r) {
canvas.sourceImage.src = r.target.result;
parent.functions.render(canvas);
parent.functions.preview(canvas, [...]);
};
})(parent);
这样,您可以使用回调中需要的计数器和其他变量。
您可以始终传递包含两个变量的单个对象。