函数在循环中创建对象时未执行 - javascript [英] function not executed when creating objects in a loop - javascript

查看:75
本文介绍了函数在循环中创建对象时未执行 - javascript的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



该函数在stage.add(layer);这一行执行,导致一个bug。



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

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

//全局参数
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(紧跟for:+ i);
edges [i] = new Kinetic.Shape({


// ***问题在这里
// ***为了循环跳过以下几行

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] .getX()+节点[i + 1] .getX()+ curvatureX)/ 2,((i + 1).getY())<0){
context.quadraticCurveTo节点[i] .getY()+ nodes [i + 1] .getY() - curvatureY)/ 2,nodes [i + 1] .getX(),nodes [i + 1] .getY()); $ b (节点[i] .getX()+节点[i + 1] .getX()+ curvatureX)/ 2,(节点[i] .getY ()+ nodes [i + 1] .getY()+ curvatureY)/ 2,no des [i + 1] .getX(),nodes [i + 1] .getY());

}
context.lineWidth = 10;
//线条颜色
context.strokeStyle =black;
context.stroke();
},

// ***循环在此恢复


填充:#00D2FF,
笔划:黑色 ,
strokeWidth:4
});
layer.add(edges [i]);
}


// ***功能在此执行,引起错误。
stage.add(layer);

var amplitude_1 = 100;
var amplitude_2 = 30;
var period = 2000;
// 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);
}
图层。 draw();

});

stage.start();
};

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


解决方案

不能使用变量声明在一个函数,并假定它的值在里面使用该函数是声明函数时的值。



在循环变量的特定情况下,该变量在调用内部函数时将具有赋给它的 last 值。



为了解决这个问题,你必须在新的作用域内关闭外部变量的值,你的情况看起来像这样:

<$ p $对于(var i = 0; i <9; ++ i){
...
drawFunc :(函数(i){//< ---------- +
return function(){// |
alert(i); //你可以在这里使用这个i
}
})(i)
}

现在, >立即调用了函数表达式 en 传递了您的循环变量 i ,但现在它的作用域中具有该变量的本地绑定副本。


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

The function gets executed at the line "stage.add(layer);", causing a bug.

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.

这篇关于函数在循环中创建对象时未执行 - javascript的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆