javascript - 当我在事件处理程序内部引用对象的参数时,即使将其设置为对象,该参数也始终为 null

标签 javascript jquery ecmascript-6 jcanvas

这是我的第一个 Stack Overflow 问题,因为我通常通过谷歌搜索找到答案,所以请耐心等待......

我正在开发一个涉及对 Canvas 元素进行大量操作的项目。为此,我导入并使用了 jQuery 和 jCanvas。我还在 ECMAScript 6 中编写代码。为了更简单的日志记录方法,我使用 loglevel(因此使用“log.debug”和“log.info”等,而不是“console.log”)。

目前,我的问题是事件处理程序与我用于存储有关每个 Canvas 的数据的对象进行了一些奇怪的交互。基本上,在我的 mousedown 和 mousemove 处理程序中,我使用 getCanvasData 函数来检索该 Canvas 的数据对象,我显然成功检索到了该数据对象,但是当我访问“dragged”参数时,它始终为 null。在代码的其他部分,我成功地将值更改为对象,但每当事件处理程序访问它时,无论如何它仍然为 null。我通过为属性创建一个 getter 和 setter 来测试它是否真的为 null,当它发生变化时打印出它的状态(我在最后提供了代码片段,它是 getCanvasData 函数中“数据”赋值的替代)。

如果您想查看当前形式的完整代码,您可以view my project where I'm currently hosting it 。这是一个实时版本,这意味着它与我的工作环境同步。当我在家里修改一些东西时,它会更新网站(所以如果你来自 future - 它可能已经关闭或完全不同)。

在网站上,移动处理程序应该负责在您生成电线/连接器时移动电线/连接器的一端(通过单击输入或输出之一)。由于处理程序无法检索“拖动”,因此连线永远不会跟随鼠标。但是,当您单击另一个输入/输出时(请记住,输入仅连接到输出,反之亦然),它将连接它们之间的电线 - 该操作是通过访问“拖动”属性来执行的(“拖动”是引用电线本身)并对其执行操作。由于您可以连接电线,这意味着“dragged”在处理程序外部被成功引用,但在处理程序内部则不然。

getCanvasData() 函数:

var canvasData = []; // (among other declarations)

function getCanvasData(canvas) {
    var data, i, tmp;
    // Retrieve the stored data
    for (i = 0; i < canvasData.length; i++) {
        tmp = canvasData[i];
        if (canvas === tmp.canvas) {
            // We got the data for our canvas!
            data = tmp;
            // We no longer need to go through the rest of the list, let's break out of the loop
            break;
        }
    }
    // Check if we got anything back
    if (!data) {
        // No data for this canvas is stored yet. We need to initialize it!
        log.info("New canvas data set is being created. Index: " + canvasData.length);
        data = {
            canvas: canvas, // The canvas this data belongs to
            gates: [],      // An array of all the logic gates on the canvas
            wires: [],      // An array of all the wires on the canvas
            spawners: [],   // An array of all the spawners on the canvas
            dragged: null,  // Currently dragged wire which should follow our mouse
            gateWidth: GATE_WIDTH,  // Width of all logic gates on this canvas
            gateHeight: GATE_HEIGHT // Height of all logic gates on this canvas
        };
        // Store the data in our storage.
        canvasData.push(data);
    }
    return data;
}

部分代码我将不同的处理程序分配给某个类的所有 Canvas :

var canvasList = $('.logicExercise'), canvas;

/* some code */

// Initialize each canvas
canvasList.each(function (i, obj) {
    canvas = $(this);
    // Initialize the data stored for the canvas
    getCanvasData(canvas);
    // Draw the UI for the canvas
    drawUI(canvas);
    // Assign mouse handlers (for spawning new wires)
    canvas.mousemove(function(event) {
        mouseMoveHandler(event, canvas);
    });
    canvas.mousedown(function(event) {
        mouseDownHandler(event, canvas);
    });
    // Prevent right-click from firing up the context menu when over the canvas
    canvas.bind('contextmenu', function(e){
        e.preventDefault();
        return false;
    });
});

mousedown 和 mousemove 处理程序:

function mouseMoveHandler(event, canvas) {
    var x = event.pageX - canvas.offset().left,
        y = event.pageY - canvas.offset().top,
        data = getCanvasData(canvas);
    if (data.dragged) {    // <--- ALWAYS NULL, AND THEREFORE FAILS
        if (data.dragged.inputs[0].type) {
            data.dragged.outputs[0].x = x;
            data.dragged.outputs[0].y = y;
            data.dragged.updateCoords();
        } else {
            data.dragged.inputs[0].x = x;
            data.dragged.inputs[0].y = y;
            data.dragged.updateCoords();
        }
    }
}

function mouseDownHandler(event, canvas) {
    var data = getCanvasData(canvas);
    if (event.which === 3) {
        // Right click detected!
        if (data.dragged) {    // <--- ALWAYS NULL, AND THEREFORE FAILS
            // We are dragging something! Right click means we need to remove it.
            data.dragged.remove();
            data.dragged = null;
        }
    }
}

我用来检查“拖动”状态变化的代码片段:

data = {
    canvas: canvas, // The canvas this data belongs to
    gates: [],      // An array of all the logic gates on the canvas
    wires: [],      // An array of all the wires on the canvas
    spawners: [],   // An array of all the spawners on the canvas
    gateWidth: GATE_WIDTH,  // Width of all logic gates on this canvas
    gateHeight: GATE_HEIGHT,// Height of all logic gates on this canvas
    _dragged: null,
    set dragged(obj) {
        log.info("'dragged' is changing to '" + obj + "'.");
        this._dragged = obj;
    },
    get dragged() {
        log.info("'dragged' is being retrieved when it's '" + this._dragged + "'.");
        return this._dragged;
    }
};

当上述代码生效时,我得到一个打印输出,通知我“拖动”更改为“对象对象”,但是当我移动鼠标(以触发 mousemove 事件)时,我得到一个打印输出,告诉我它是“null” '(甚至不是未定义的)。当我的项目的其他部分使用它时,它会成功使用它并实际检索该对象。

最佳答案

您应该使用if (canvas[0] === tmp.canvas[0])引用实际的 Canvas 对象,而不是传入 getCanvasData() 的 jQuery 选择器.

当您检查if (canvas === tmp.canvas)时您正在检查 jQuery 选择器,而不是而不是实际的 Canvas 对象。因此,在一个地方您可能会经过 $("canvas#foo")以及您正在经过的其他地方 $("canvas .foo")它们具有不同的上下文,并且不会彼此 ==。

关于javascript - 当我在事件处理程序内部引用对象的参数时,即使将其设置为对象,该参数也始终为 null,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35142699/

相关文章:

javascript - 调整 jQuery 字数计数器以将 URL 计为 3 个字

javascript - ECMAScript 6 类属性下划线前缀

javascript - 相当于 YUI Lang.sub 函数的 jQuery

javascript - 如果文档可以垂直滚动 200px 或更多运行函数

javascript - 替换使用 ajax 的页面上的内容

javascript - API 开发、Bootstrap 和 jQuery。将它们全部注入(inject)用户代码中是个好主意吗?

jQuery live 和 prop 和change

javascript - 如何通过 Javascript 中的切换类选择元素?

Javascript - 对象字段未定义

javascript - React.js : Add/Remove input field on click of a button