There are lots of correct answers, here, depending on the size of your application and whom you’re delivering it to (by whom, I mean intended devices, et cetera), and how much work you can do server-side to ensure that you’re targeting the correct devices (this is still a long way from 100% viable for most non-enterprise mortals).
When building your application, “classes” can reside in their own files, happily.
When splitting an application across files, or when dealing with classes with constructors that assume too much (like instantiating other classes), circular-references or dead-end references ARE a large concern.
There are multiple patterns to deal with this, but the best one, of course is to make your app with DI/IoC in mind, so that circular-references don’t happen.
You can also look into require.js or other dependency-loaders. How intricate you need to get is a function of how large your application is, and how private you would like everything to be.
When serving your application, the baseline for serving JS is to concatenate all of the scripts you need (in the correct order, if you’re going to instantiate stuff which assumes other stuff exists), and serve them as one file at the bottom of the page.
But that’s baseline.
Other methods might include “lazy/deferred” loading.
Load all of the stuff that you need to get the page working up-front.
Meanwhile, if you have applets or widgets which don’t need 100% of their functionality on page-load, and in fact, they require user-interaction, or require a time-delay before doing anything, then make loading the scripts for those widgets a deferred event. Load a script for a tabbed widget at the point where the user hits mousedown on the tab. Now you’ve only loaded the scripts that you need, and only when needed, and nobody will really notice the tiny lag in downloading.
Compare this to people trying to stuff 40,000 line applications in one file.
Only one HTTP request, and only one download, but the parsing/compiling time now becomes a noticeable fraction of a second.
Of course, lazy-loading is not an excuse for leaving every class in its own file.
At that point, you should be packing them together into modules, and serving the file which will run that whole widget/applet/whatever (unless there are other logical places, where functionality isn’t needed until later, and it’s hidden behind further interactions).
You could also put the loading of these modules on a timer.
Load the baseline application stuff up-front (again at the bottom of the page, in one file), and then set a timeout for a half-second or so, and load other JS files.
You’re now not getting in the way of the page’s operation, or of the user’s ability to move around. This, of course is the most important part.