简体   繁体   中英

Javascript error ; while trying locally

the below code gives "Uncaught TypeError: Cannot call method 'getContext' of undefined". The code is my experiment to port a canvas app using module pattern as described here .

Please find the same code in jsfiddle , which works fine.

thanks.

//====test.html ========

<html>
<head>
    <title>Location</title>
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
    <script type="text/javascript" src="test.js"></script>
</head>

<body>
<canvas id="cvs" height="600" width="800"></canvas>
</body>
</html>

//==test.js ========

if (typeof (NS) === 'undefined') {
    NS = {};
}

NS.AppName = (function ($) {
// Private members
    /*var _first = function () {
    },
    _second = function () {
    },*/
    var _cvs = $("#cvs");
    var _ctx = _cvs.get(0).getContext("2d");    

    var _privateVar = "privateVar: accessed from within AppLaunch.Admin namespace";
    // Private Methods
    var _privateMethod = function () {
       log("privateMethod: accessed only from within AppLaunch.Admin");
    }; // Last variable in a chain must always end with ; before the return {}

    function log() {
        if (window.console && window.console.log)
            window.console.log('[AppName] ' + Array.prototype.join.call(arguments, ' '));
    };

    return {
        init: function () {
        },

        // Public
        myPublicMethod: function() {
            //alert("myPublicMethod" + _cvs.height());
            _ctx.fillRect(25,25,100,100);
    _ctx.clearRect(45,45,60,60);
    _ctx.strokeRect(50,50,50,50);
        }
    }
})(jQuery); 

// Initialize
jQuery().ready(function() {
    NS.AppName.init()
    NS.AppName.myPublicMethod();
});  

Your ready handler syntax is incorrect - try this:

jQuery(document).ready(function() {
    NS.AppName.init();
    NS.AppName.myPublicMethod();
});

Or

jQuery(function() {
    NS.AppName.init();
    NS.AppName.myPublicMethod();
});

I don't get an error. But perhaps something is lost in translation from you c/ping it here. Perhaps (and this is just a guess), put a; on the end of that NS.AppName.init() maybe you have some funky whitespace/returns going on there...

Moving the JS to body solved the problem:

    <html>
<head>
    <title>Location</title>
</head>

<body>
<canvas id="cvs" height="600" width="800"></canvas>
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
    <script type="text/javascript" src="test.js"></script>
</body>
</html>

or

    <html>
<head>
    <title>Location</title>
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
</head>

<body>
<canvas id="cvs" height="600" width="800"></canvas>     
    <script type="text/javascript" src="test.js"></script>
</body>
</html>

The reason you get an error is that the self executing anonymous function used to initialize NS.AppName is invoked in place (right where it is defined), and not when the DOM is ready.

NS.AppName = (function ($) {
  //1: some code
  return function(){...}//2
}(jQuery));//3

$(function(){
  NS.AppName();//4
});

line 3 is the self executing part. It calls the anonymous function declared above.

During the call of line 3 the body of the anonymous function will be executed ( including line 1 , but not anything inside the function at line 2 ). If the document is not loaded when this happens (ex: if the script is in the head), than it will fail because there is no $("#cvs") in the DOM yet.

Line 4 will call the function defined at line 2 when the DOM is fully loaded ( $(f) is equivalent to $(document).ready(f) ).

Here is some more info about self executing anonymous functions, or using a better name " Immediately-Invoked Function Expression "

You can fix the script in three ways:

  • Remove any references to the DOM from the anonymous function, and move them in the returned one (I'd do this, it's just one element...)
  • Wrap the entire script in jQuery(function($){...(you can safely use $ here, so no need for the anonymous functions)...}); - execute it all on DOM ready
  • Move it at the bottom of the page (not ideal, but it would work)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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