代码之家  ›  专栏  ›  技术社区  ›  rymn

jquery-请向我解释闭包、变量上下文

  •  0
  • rymn  · 技术社区  · 16 年前

    好吧,我不明白为什么火狐会说$(canvas”)[0].getContext('2d');未定义。我把它从函数中去掉,这样所有的函数都可以访问它,但是这里CTX仍然是未定义的。

    (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);
    

    但是,当我将CTX的位置转移到未命名的函数时,CTX并不是未定义的:

    (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);
    

    第一个代码有什么问题?我的意思是var ctx是在顶部声明的。所以这将使它成为一个全局变量。嗯,我得到的错误是$(“画布”)[0]未定义。意味着它无法访问画布。为什么??

    2 回复  |  直到 16 年前
        1
  •  3
  •   Seb    16 年前

    这是因为在第一次调用中,您实际上正在创建一个函数对象,该对象只有在另一个上下文中加载了DOM之后才会被处理。

    当页面中的所有元素都已加载时,将调用该匿名函数,因此调用方将是jquery核心函数,其上下文与您在此处编码的上下文完全不同。

    我建议把所有东西都包在里面 $() 打电话,这样应该可以:

    (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);
    
        2
  •  4
  •   brianpeiris    16 年前

    我想你搞错了问题。不是您误解了变量上下文,而是您可能正在运行javascript 之前 您的画布标签已声明。

    下面的代码演示了这个问题。它将显示消息“canvasene is undefined!”因为我们试图进入 canvasOne 在声明之前(注意 <canvas> 标签)。

    我在这里创建了一个托管演示: http://jsbin.com/afuju 可编辑的 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>