简体   繁体   English

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

[英]function not executed when creating objects in a loop - javascript

In the following code the drawFunc is not executed during the loop (I can see that with a step-by-step-debugging, the code just jumps to the end of the function). 在以下代码中,drawFunc在循环期间未执行(我可以看到,通过逐步调试,代码仅跳至函数的末尾)。

The function gets executed at the line "stage.add(layer);", causing a bug. 该函数在“ stage.add(layer);”行执行,从而导致错误。

Any help on how to fix this? 任何有关如何解决此问题的帮助?

<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>

You cannot use a variable declared outside a function and assume that its value when used inside that function is what it was at the time the function was declared. 不能使用函数外部声明的变量,并且不能假定该变量该函数内部使用时的值与声明该函数时的值相同。

In the particular case of a loop variable, that variable will have the last value assigned to it by the time the inner function is called. 在循环变量的特定情况下,在调用内部函数时,该变量将被分配有最后一个值。

To fix this, you have to "close" the outer variable's value inside a new scope, in your case that would look like this: 要解决此问题,您必须在新的作用域内“关闭”外部变量的值,在这种情况下,应如下所示:

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

The unusual looking construct now there is an immediately invoked function expression which has been passed your loop variable i , but now has a locally bound copy of that variable in its scope. 现在,外观异常的构造中有一个立即调用的函数表达式 ,该函数表达式传递给循环变量i ,但现在在其作用域中具有该变量的本地绑定副本。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM