Coffeescript的范围问题

时间:2013-07-03 14:25:24

标签: javascript scope coffeescript

我在Coffeescript中有一些奇怪的范围问题。

我无法从函数@qr.callback访问_this,_这似乎没有通过。我永远不会改变this.imgName,所以它不起作用的唯一原因可能就是_这不是很好。

decode:(@callback) ->
    _this= this
    console.log 'before',_this.imgName
    @qr= new QrCode()
    @qr.callback= () ->
        console.log "after:", _this.imgName
    @qr.decode("data:image/png;base64,#{@base64Data}")

Console Output

编辑:

我尝试过使用

    console.log 'before',@imgName
    @qr= new QrCode()

    @qr.callback= () =>
        console.log "after:", @imgName
    @qr.decode("data:image/png;base64,#{@base64Data}")

但输出相同

Edit2:QrCode代码:此代码来自https://github.com/LazarSoft/jsqrcode。但是,由于LazarSoft https://github.com/LazarSoft/jsqrcode/blob/master/src/qrcode.js的源代码没有包含可以多次实例化的QrCode对象,我通过创建QrCode函数而不是全局对象qrcode来转换代码以创建许多不同的QrCode实例。

QrCode= function ()
  {
    this.imagedata = null;
    this.width = 0;
    this.height = 0;
    this.qrCodeSymbol = null;
    this.debug = false;

this.sizeOfDataLengthInfo =  [  [ 10, 9, 8, 8 ],  [ 12, 11, 16, 10 ],  [ 14, 13, 16, 12 ] ];

this.callback = null;

this.decode = function(src){

    if(arguments.length==0)
    {
        var canvas_qr = document.getElementById("qr-canvas");
        var context = canvas_qr.getContext('2d');
        this.width = canvas_qr.width;
        this.height = canvas_qr.height;
        this.imagedata = context.getImageData(0, 0, this.width, this.height);
        this.result = this.process(context);
        if(this.callback!=null)
            this.callback(this.result);
        return this.result;
    }
    else
    {
        var image = new Image();
        _this=this
        image.onload=function(){
            //var canvas_qr = document.getElementById("qr-canvas");
            var canvas_qr = document.createElement('canvas');
            var context = canvas_qr.getContext('2d');
            var canvas_out = document.getElementById("out-canvas");
            if(canvas_out!=null)
            {
                var outctx = canvas_out.getContext('2d');
                outctx.clearRect(0, 0, 320, 240);
                outctx.drawImage(image, 0, 0, 320, 240);
            }
            canvas_qr.width = image.width;
            canvas_qr.height = image.height;
            context.drawImage(image, 0, 0);
            _this.width = image.width;
            _this.height = image.height;
            try{
                _this.imagedata = context.getImageData(0, 0, image.width, image.height);
            }catch(e){
                _this.result = "Cross domain image reading not supported in your browser! Save it to your computer then drag and drop the file!";
                if(_this.callback!=null)
                    _this.callback(_this.result);
                return;
            }

            try
            {
                _this.result = _this.process(context);
            }
            catch(e)
            {
                // console.log('error:'+e);
                _this.result = "error decoding QR Code";
            }
            if(_this.callback!=null)
                _this.callback(_this.result);
        }
        image.src = src;
    }
}

this.decode_utf8 = function ( s )
{
  return decodeURIComponent( escape( s ) );
}

this.process = function(ctx){

    var start = new Date().getTime();

    var image = this.grayScaleToBitmap(this.grayscale());
    //var image = this.binarize(128);

    if(this.debug)
    {
        for (var y = 0; y < this.height; y++)
        {
            for (var x = 0; x < this.width; x++)
            {
                var point = (x * 4) + (y * this.width * 4);
                this.imagedata.data[point] = image[x+y*this.width]?0:0;
                this.imagedata.data[point+1] = image[x+y*this.width]?0:0;
                this.imagedata.data[point+2] = image[x+y*this.width]?255:0;
            }
        }
        ctx.putImageData(this.imagedata, 0, 0);
    }

    //var finderPatternInfo = new FinderPatternFinder().findFinderPattern(image);

    var detector = new Detector(image,this);

    var qRCodeMatrix = detector.detect();

    /*for (var y = 0; y < qRCodeMatrix.bits.Height; y++)
    {
        for (var x = 0; x < qRCodeMatrix.bits.Width; x++)
        {
            var point = (x * 4*2) + (y*2 * this.width * 4);
            this.imagedata.data[point] = qRCodeMatrix.bits.get_Renamed(x,y)?0:0;
            this.imagedata.data[point+1] = qRCodeMatrix.bits.get_Renamed(x,y)?0:0;
            this.imagedata.data[point+2] = qRCodeMatrix.bits.get_Renamed(x,y)?255:0;
        }
    }*/
    if(this.debug)
        ctx.putImageData(this.imagedata, 0, 0);

    var reader = Decoder.decode(qRCodeMatrix.bits,this);
    var data = reader.DataByte;
    var str="";
    for(var i=0;i<data.length;i++)
    {
        for(var j=0;j<data[i].length;j++)
            str+=String.fromCharCode(data[i][j]);
    }

    var end = new Date().getTime();
    var time = end - start;
    console.log(time);

    return this.decode_utf8(str);
    //alert("Time:" + time + " Code: "+str);
}

this.getPixel = function(x,y){
    if (this.width < x) {
        throw "point error";
    }
    if (this.height < y) {
        throw "point error";
    }
    point = (x * 4) + (y * this.width * 4);
    p = (this.imagedata.data[point]*33 + this.imagedata.data[point + 1]*34 + this.imagedata.data[point + 2]*33)/100;
    return p;
}

this.binarize = function(th){
    var ret = new Array(this.width*this.height);
    for (var y = 0; y < this.height; y++)
    {
        for (var x = 0; x < this.width; x++)
        {
            var gray = this.getPixel(x, y);

            ret[x+y*this.width] = gray<=th?true:false;
        }
    }
    return ret;
}

this.getMiddleBrightnessPerArea=function(image)
{
    var numSqrtArea = 4;
    //obtain middle brightness((min + max) / 2) per area
    var areaWidth = Math.floor(this.width / numSqrtArea);
    var areaHeight = Math.floor(this.height / numSqrtArea);
    var minmax = new Array(numSqrtArea);
    for (var i = 0; i < numSqrtArea; i++)
    {
        minmax[i] = new Array(numSqrtArea);
        for (var i2 = 0; i2 < numSqrtArea; i2++)
        {
            minmax[i][i2] = new Array(0,0);
        }
    }
    for (var ay = 0; ay < numSqrtArea; ay++)
    {
        for (var ax = 0; ax < numSqrtArea; ax++)
        {
            minmax[ax][ay][0] = 0xFF;
            for (var dy = 0; dy < areaHeight; dy++)
            {
                for (var dx = 0; dx < areaWidth; dx++)
                {
                    var target = image[areaWidth * ax + dx+(areaHeight * ay + dy)*this.width];
                    if (target < minmax[ax][ay][0])
                        minmax[ax][ay][0] = target;
                    if (target > minmax[ax][ay][1])
                        minmax[ax][ay][1] = target;
                }
            }
            //minmax[ax][ay][0] = (minmax[ax][ay][0] + minmax[ax][ay][1]) / 2;
        }
    }
    var middle = new Array(numSqrtArea);
    for (var i3 = 0; i3 < numSqrtArea; i3++)
    {
        middle[i3] = new Array(numSqrtArea);
    }
    for (var ay = 0; ay < numSqrtArea; ay++)
    {
        for (var ax = 0; ax < numSqrtArea; ax++)
        {
            middle[ax][ay] = Math.floor((minmax[ax][ay][0] + minmax[ax][ay][1]) / 2);
            //Console.out.print(middle[ax][ay] + ",");
        }
        //Console.out.println("");
    }
    //Console.out.println("");

    return middle;
}

this.grayScaleToBitmap=function(grayScale)
{
    var middle = this.getMiddleBrightnessPerArea(grayScale);
    var sqrtNumArea = middle.length;
    var areaWidth = Math.floor(this.width / sqrtNumArea);
    var areaHeight = Math.floor(this.height / sqrtNumArea);
    var bitmap = new Array(this.height*this.width);

    for (var ay = 0; ay < sqrtNumArea; ay++)
    {
        for (var ax = 0; ax < sqrtNumArea; ax++)
        {
            for (var dy = 0; dy < areaHeight; dy++)
            {
                for (var dx = 0; dx < areaWidth; dx++)
                {
                    bitmap[areaWidth * ax + dx+ (areaHeight * ay + dy)*this.width] = (grayScale[areaWidth * ax + dx+ (areaHeight * ay + dy)*this.width] < middle[ax][ay])?true:false;
                }
            }
        }
    }
    return bitmap;
}

this.grayscale = function(){
    var ret = new Array(this.width*this.height);
    for (var y = 0; y < this.height; y++)
    {
        for (var x = 0; x < this.width; x++)
        {
            var gray = this.getPixel(x, y);

            ret[x+y*this.width] = gray;
        }
    }
    return ret;
}

  }

1 个答案:

答案 0 :(得分:1)

 var image = new Image();
 _this=this

可能闪电击中你,你太过编码CoffeeScript了!你在这里忘记了var声明,所以decode的第九次调用用_this实例覆盖全局this - 当每次解码完成时,它们都会调用相同的回调。

使用

修复它
var _this = this;

var image = new Image,
    _this = this;

或在任何地方使用CoffeeScript: - )