Consider this Coffeescript class, in an app where each class lives in its own file.
class Manager extends Person
title: titles["manager"]
If that file is loaded before the "titles" object, an error generated. I'm assuming this is because of Coffeescripts safety wrapper which is performing ".call(this)" when this file is first loaded?
Otherwise, if I were to delay running any code until after the entire page had fully loaded ($(document.ready()), I could be sure that all the javascript files were fully loaded before any code actually ran.
Doesn't this create some annoying load order problems, or am I not doing something correctly?
It is indeed a load order problem, and
titles
inManager
refers to a global in this case, that isn't declared at this point. If you knowtitles
is declared globally somewhere else, you must manually ensure that script has been loaded first. And yes, the problem may very well be with the safety wrapper. But just as a recommendation: it's there for a good reason. Create yourself a namespace instead that you export to the global object. The global object lives inthis
(at definition time) orexports
in Node. I usually put this one-liner on top of scripts that should have easy access to the global object:From there I can put things in the global object, like a namespace:
Now, there will be an 'app' object in your global object with a 'class' (so to speak) and and object.
Give a try to CoffeeToaster:
http://github.com/serpentem/coffee-toaster
It'll do exactly what you're looking for by providing
import
directive, which is#<<
, i.e.:You don't need to inform the
.coffee
extension, plus you can turn on thepackaging
option to have namespaces facilities, if you're used to something like:It has a build system that will output a single javascript file for you, or several (in debug mode) for easing the debugging process.
Take a look on the
README
and the usage example at:https://github.com/serpentem/coffee-toaster/tree/master/usage
It can't be both an order issue and a wrapper issue. Wrapping something with a function that's run immediately has no effect on order, only on scope.
And if
titles
is defined in another file, then the scoping ofclass Manager
doesn't matter. So, it's an order issue. How istitles
defined?Not quite.
$(document).ready()
(note the parentheses—there is nodocument.ready
function...) delays a function's execution until all of the page's HTML has been loaded, which doesn't mean all JavaScript has been loaded. Here's the good news: From the standpoint of JavaScript code, it doesn't matter whether other JavaScript files have been loaded, because they're all run in order. (Note: I'm assuming here that you're not doing anything fancy like adding additional<script>
tags from your JavaScript code.) So as long as you haveyou can rest assured that
Manager.js
will only run aftertitles.js
has.Warning! Relying on
$(document).ready()
for ordering JS code is a common mistake that can lead to confusion! If your HTML looked like thiswhere
titles.js
creates a global calledtitles
andManager.js
looks like thisthen the output will sometimes be
titles
, and sometimes beundefined
. Why? Because as the docs say,And the DOM may already have been initialized when the first JS file is run! (In practice, this will tend to happen if the browser has the page's HTML cached.)
So, keep it simple. Just load your scripts in the right order. Remember that, for all practical purposes, your scripts are concatenated together by the browser, in order, into a single JS file.