JQuery- Please explain to me Closure, variable context

Ok, so I don't understand why Firefox says $ ("# canvas") [0] .getContext ('2d'); undefined. I laid it out from within a function so that all functions can access it, but here the ctx is still undefined.

(function($) {
        // Undefined
        var ctx = $('#canvas')[0].getContext("2d");
        var x = 150;
        var y = 150;
        var dx = 2;
        var dy = 4;
        $(function() {
            setInterval(draw, 10);
        })
        function draw() {
            ctx.clearRect(0,0,300,300);
            ctx.beginPath();
            ctx.arc(x,y,10,0,Math.PI*2,true);
            ctx.closePath();
            ctx.fill();
            x+=dx;
            y+=dy;
        }
    })(jQuery);

      

However, when I passed the ctx location to the unnamed function, the ctx is not undefined:

(function($) {
        var ctx;
        var x = 150;
        var y = 150;
        var dx = 2;
        var dy = 4;
        $(function() {
              //Not Undefined
            ctx = $("#canvas")[0].getContext('2d');
            setInterval(draw, 10);
        })
        function draw() {
            ctx.clearRect(0,0,300,300);
            ctx.beginPath();
            ctx.arc(x,y,10,0,Math.PI*2,true);
            ctx.closePath();
            ctx.fill();
            x+=dx;
            y+=dy;
        }
    })(jQuery);

      

What's wrong with the first code? I mean var ctx is declared on top. So this will make it a global variable. Hmm, the error I got is $ ("# canvas") [0] - undefined. So he can't access #canvas .. Why?

0


a source to share


2 answers


This is because the first time you call, you are actually creating a Function object, which will only be processed after the DOM has loaded, in a different context.

This anonymous function will be called when all the elements on the page have already loaded, so the caller will be the main jQuery function and its context is completely different from the one you are coding here.



I would suggest wrapping everything inside a call $()

, so this should work:

(function($) {
        $(function() {
            var ctx = $("#canvas")[0].getContext('2d');
            var x = 150;
            var y = 150;
            var dx = 2;
            var dy = 4;

            setInterval(draw, 10);

            function draw() {
                    ctx.clearRect(0,0,300,300);
                    ctx.beginPath();
                    ctx.arc(x,y,10,0,Math.PI*2,true);
                    ctx.closePath();
                    ctx.fill();
                    x+=dx;
                    y+=dy;
            }
        });
})(jQuery);

      

+3


a source


I think you are wrong about this problem. It's not that you misunderstood your variable context, but you are probably using javascript before declaring the canvas tag.

The following code demonstrates the problem. The message "canvasOne - undefined!" Will appear. because we are trying to access canvasOne

prior to its announcement (note the placement of tags <canvas>

).



I created a demo posted here: http://jsbin.com/afuju (Editable via http://jsbin.com/afuju/edit )

<html>
  <head>
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
  </head>
  <body>
    <script>
      /* 
        The following line of code is run as soon as the browser sees it.
        Since the "canvasOne" tag is not declared yet, the variable will be undefined.
      */
      var canvasOne = $('#canvasOne')[0];

      $(function() {
        // The following code is run after the whole document has finished loading.
        if (canvasOne === undefined) {
          alert('canvasOne is undefined!');
        }
        else {
          canvasOne.getContext("2d").fillRect(5, 5, 15, 15);
        }
      });
    </script>
    <canvas id="canvasOne"></canvas>



    <canvas id="canvasTwo"></canvas>

    <script>
      /* 
        The following line of code is run as soon as the browser sees it.
        But since the "canvasTwo" tag *is* declared above, the variable will *not* be undefined.
      */
      var canvasTwo = $('#canvasTwo')[0];

      $(function() {
        // The following code is run after the whole document has finished loading.
        if (canvasTwo === undefined) {
          alert('canvasTwo is undefined!');
        }
        else {
          canvasTwo.getContext("2d").fillRect(5, 5, 15, 15);
        }
      });
    </script>



    <script>
      $(function() {
        /*
          The following code is run after the whole document has finished loading.
          Hence, the variable will *not* be undefined even though the "canvasThree" tag appears after the code.
        */
        var canvasThree = $('#canvasThree')[0];
        if (canvasThree === undefined) {
          alert('canvasThree is undefined!');
        }
        else {
          canvasThree.getContext("2d").fillRect(5, 5, 15, 15);
        }
      });
    </script>

    <canvas id="canvasThree"></canvas>
  </body>
</html>

      

+4


a source







All Articles