0

用 RaphaelJS 库绘制一组圆。

对于每个圆圈,我想创建一个onclick传递变量的函数,但在这个函数中,我的变量是未定义的。

问题是什么?

这是我的代码:

//children is an array such as [1,2,4[5,6,7]]
for (var i = 0; i < children.length; i++) {
    var array = children;
    alert("ARRAY[0]===" + array[0])

    var st = space2Draw.set();
    st.push(space2Draw.circle(xChildren, yChildren, 20).click(function (array) {
        //array[i] is undefined
        alert("ARRAY[i]===" + array[i]);
        //retrive(array[i]);
    }),
    LineRoot(xRadice, yRadice, xChildren, yChildren, space2Draw));
    space2Draw.text(xChildren, yChildren, children[i]).attr({
        fill: "white"
    });
    st.attr({
        fill: "red"
    });

    xChildren += 50;
}
4

2 回答 2

2

您的点击回调不应该有“数组”参数,它会覆盖父范围的“数组”变量。您可以删除参数,它应该没问题。

我认为您会遇到另一个问题,即 i 在您的点击回调中始终是 children.length(因为函数范围实际上将在循环结束时关闭。更多信息在这里)。您应该创建一个辅助函数来为您创建回调。

你可以尝试这样的事情:

//children is an array such as [1,2,4[5,6,7]]
for (var i = 0; i < children.length; i++) {
    var array = children;
    alert("ARRAY[0]===" + array[0])

    var st = space2Draw.set();
    st.push(space2Draw.circle(xChildren, yChildren, 20).click(getCallback(array , i)),
    LineRoot(xRadice, yRadice, xChildren, yChildren, space2Draw));
    space2Draw.text(xChildren, yChildren, children[i]).attr({
        fill: "white"
    });
    st.attr({
        fill: "red"
    });

    xChildren += 50;
}

function getCallback(array , i){
   return function () {
        alert("ARRAY[i]===" + array[i]);
    }
}
于 2013-04-30T13:01:07.220 回答
1

You should do this:

...
st.push(space2Draw.circle(xChildren, yChildren, 20).click((function (array, i) {
    return function () {
        //array[i] is undefined
        alert("ARRAY[i]===" + array[i]);
        //retrive(array[i]);
    }
}(array, i)));
...

The reason why this works is that in javascript, scope is defined by functions, not by blocks.

Your callback gets access (by closure) to the array and i (among other variables), but when the callback gets executed, i is equal to children.length, because the loop has finished iterating.

By using IIFE (immediately invocation function expression) we create a new scope, and the callback gets access to the current value of array and i.


Also, the click function calls the callback by passing an event object as first parameter, so our IIFE should return this

return function (event) {
    // access array and i by closure
    // event is the event representing the click
    // event, provided by Raphael

    // do something
}
于 2013-04-30T13:02:26.293 回答