在循环中创建对象时不执行函数 - javascript

时间:2012-05-30 09:45:29

标签: javascript function

在下面的代码中,循环期间不执行drawFunc(我可以看到,通过逐步调试,代码只是跳转到函数的末尾)。

该函数在“stage.add(layer);”行执行,导致错误。

有关如何解决此问题的任何帮助?

<html>
    <head>
        <style>
            body {
                margin: 0px;
                padding: 0px;
            }
            canvas {
                border: 1px solid #9C9898;
            }
        </style>
        <script type="text/javascript" src="http://www.html5canvastutorials.com/libraries/kinetic-v3.9.7.js"></script>
        <script>
            window.onload = function() {

                // global parameters
                var curvatureX = 10;
                var curvatureY = 10;
                var nodeRadius = 10;

                var stage = new Kinetic.Stage({
                    container: "container",
                    width: 578,
                    height: 300
                });
                var layer = new Kinetic.Layer();


                var nodes = [];

                for (var i = 0;i<10;i++){
                    nodes[i] = new Kinetic.Circle({
                        x: i*20,
                        y: i*5,
                        z:1,
                        radius: nodeRadius,
                        fill: "blue",
                        stroke: "black",
                        strokeWidth: 4
                    });
                    layer.add(nodes[i]);


                }


                var edges = [];
                for (var i = 0;i<9;i++){
                    console.log("just after the for: "+i);
                    edges[i]= new Kinetic.Shape({


// *** PROBLEMS IS HERE
// *** FOR LOOP SKIPS THE FOLLOWING LINES

                        drawFunc: function() {
                            var context = this.getContext();
                            context.beginPath();
                            console.log("in the drawing function: "+i);
                            context.moveTo(nodes[i].getX(), nodes[i].getY());
                            if ((nodes[i].getY()-nodes[i+1].getY())<0){
                                context.quadraticCurveTo((nodes[i].getX()+nodes[i+1].getX()+curvatureX)/2, (nodes[i].getY()+nodes[i+1].getY()-curvatureY)/2, nodes[i+1].getX(), nodes[i+1].getY());
                            }
                            else{
                                context.quadraticCurveTo((nodes[i].getX()+nodes[i+1].getX()+curvatureX)/2, (nodes[i].getY()+nodes[i+1].getY()+curvatureY)/2, nodes[i+1].getX(), nodes[i+1].getY());

                            }
                            context.lineWidth = 10;
                            // line color
                            context.strokeStyle = "black";
                            context.stroke();
                        },

// *** LOOP RESUMES HERE


                        fill: "#00D2FF",
                        stroke: "black",
                        strokeWidth: 4
                    });
                    layer.add(edges[i]);
                }


                //*** FUNCTION IS EXECUTED HERE, CAUSING BUG.
                stage.add(layer);

                var amplitude_1 = 100;
                var amplitude_2 = 30;
                var period = 2000;
                // in ms
                var centerX = stage.getWidth() / 2;
                var centerY = stage.getHeight() / 2;

                stage.onFrame(function(frame) {
                    for (var i=0;i<nodes.length;i++){
                        nodes[i].setX(amplitude_1 * i * Math.sin(frame.time * 2 * Math.PI / period) + centerX);
                        nodes[i].setY(amplitude_2 * i+ 20);
                    }
                    layer.draw();

                });

                stage.start();
            };

        </script>
    </head>
    <body>
        <div id="container"></div>
    </body>
</html>

1 个答案:

答案 0 :(得分:1)

不能使用一个声明之外的函数的函数,并假设它在里面时使用的那个函数就是当时的函数声明了这个功能。

在循环变量的特定情况下,该变量将在调用内部函数时为其分配 last 值。

要解决此问题,您必须在新范围内“关闭”外部变量的值,在您的情况下如下所示:

for (var i = 0; i < 9; ++i) {
    ...
    drawFunc: (function(i) {  //  <------------+
        return function() {   //               |
            alert(i);         // you can use this "i" here
        }
    })(i)
}

看起来不寻常的构造现在有一个立即调用的函数表达式已经传递你的循环变量i,但现在有一个本地绑定的副本该范围内的变量。