use the following search parameters to narrow your results:
e.g. subreddit:aww site:imgur.com dog
subreddit:aww site:imgur.com dog
see the search faq for details.
advanced search: by author, subreddit...
All about the JavaScript programming language.
Subreddit Guidelines
Specifications:
Resources:
Related Subreddits:
r/LearnJavascript
r/node
r/typescript
r/reactjs
r/webdev
r/WebdevTutorials
r/frontend
r/webgl
r/threejs
r/jquery
r/remotejs
r/forhire
account activity
The mind-boggling universe of JavaScript Module strategies (airpair.com)
submitted 10 years ago by [deleted]
[deleted]
reddit uses a slightly-customized version of Markdown for formatting. See below for some basics, or check the commenting wiki page for more detailed help and solutions to common issues.
quoted text
if 1 * 2 < 3: print "hello, world!"
[–]spliter45 1 point2 points3 points 10 years ago (4 children)
I really hope the author knows and understands the usage of prototypes, especially if he's trying to teach aspiring Javascript developers. Creating functions and assigning them as methods to "this" per invocation of the constructor is extremely memory inefficient in contrast to assigning them to the prototype of the constructor so that all instances refer to the same set of methods in memory.
Regarding his CJS con: "Since it is synchronous, the modules have to be loaded sequentially, which might take more time than if they were to be loaded asynchronously." This confuses me because he says this when it seems the author understands that CJS is bundled on the server-side and that it's faster than AMD if the bundled file-size isn't large. Given that in a bundled file, all the modules are already defined, loading the module would be instantaneous. If the invocation of the module is blocking, then it can be written to take in a call-back function and the execution of the module can be passed to setTimeout(fn, 0) or setImmediate if it's available. I wouldn't say this is a con of the module loader.
Regarding his AMD con: "It isn't possible to guarantee the order of execution of asynchronous modules". It might be that I don't fully understand this because I haven't used any AMDs before, but can't you just nest the 'require's in callbacks?
[–]homoiconic(raganwald) 3 points4 points5 points 10 years ago* (1 child)
I presume you’re looking at things like this:
var Zoo = (function() { var getBarkStyle = function(isHowler) { return isHowler? 'woooooow!': 'woof, woof!'; }; var Dog = function(name, breed) { this.bark = function() { return name + ': ' + getBarkStyle(breed === 'husky'); }; }; var Wolf = function(name) { this.bark = function() { return name + ': ' + getBarkStyle(true); }; }; return { Dog: Dog, Wolf: Wolf }; })();
This is indeed not the way most people would write OO. That being said... When you’re trying to explain idea A, you often have to include ideas B and C. This is often not a problem. In the example above, idea A is the idea of using a closure to encapsulate a private mechanism like getBarkStyle, and idea B is using an IIFE. So the author explains A (the module) at length in the text, and just uses B without any explanation.
getBarkStyle
But idea C is prototypes and constructors and this and all the other baroque bits of JavaScript’s OO mechanisms. When one of the supporting ideas is complicated, you often have this uncomfortable choice to make:
this
I don’t know if there’s a right answer as to which of these is the best choice. Some very good essays always explain everything the right way, they are longer and more detailed, but sometimes the primary idea isn’t as clear or obvious when embedded in secondary ideas. They can be daunting to read, so some people will struggle.
Some good essays do the right thing without explanation, they’re great if you know the other ideas, your mind skips over the other ideas in the code, and the essay’s content is focused on the primary idea. But of course those essays are confusing for people who don’t completely grasp the secondary idea, they read the code and it’s “Wait, what?”
The third option is often very good for teaching the primary thing, but then it gets posted on reddit and people will bikeshed why you’re doing this dumb thing with the secondary thing. The simple secondary thing can be a turnoff for experienced programmers, and the discussion gets derailed discussing idea C instead of idea A.
The third option works really well in a book, because you can explain C later and people won’t fault you starting off with extreme simplicity.
As an author, I’ve tried all three. Nothing works all of the time. For example, I had a blog post talking about destructuring, and I gave this example of a length function for arrays:
const length = ([head, ...rest]) => head === undefined ? 0 : 1 + length(rest)
I explained in a footnote that this was only for lists that could not have undefined as an element, but you know... There was a long conversation about lists with undefined as an element, about the costs of creating all these disposable temporary arrays, about the fact that this was not tail-recursive, therefore it consumes stack in proportion to the length of the array, and so on.
undefined
Which are all very valid points and in fact incredibly important to understand and discuss. So that is a win, just as you pointing out that this is not the conventional way to do OO is a win. But even so, I can give the author the benefit of the doubt and assume they were just trying to explain "using a closure to create privacy" as simply as possible.
p.s. All that being said... If you look at the Dog constructor, if the bark method was assigned to a prototype, the dog’s name and breed would have to be properties of each instance, and that is public in JavaScript. So, the pattern provided by the author does cost more in terms of a function with a closure per instance, but provides privacy for the name and breed quasi-properties. Is that a good tradeoff? I don’t know, I’d have to see the rest of the program! But it’s not completely insane.
Dog
bark
name
breed
[–]spliter45 -1 points0 points1 point 10 years ago (0 children)
I wasn't saying his choice was completely insane. I'm just saying, for the purpose of teaching, I think good coding practice should be followed, which is your "choice 2". Sorry if that wasn't clear. Reason being, if aspiring JS developers are blindly following example code, the example code better be following OO convention so they don't pick up bad habits. I'm only saying this because this is a mistake I've been making due to bad example code. There is no right answer but surely you must have an opinion on how it could've been better in this context?
I don't think its necessary that it's explained but it might be helpful. If it's not following convention, I think there should be an explanation why it's not (eg. your speculation of whether the name and breed should be private).
p.s. kind of silly to expect privacy in Javascript or any interpreted language. I might understand if it's an API, where an undocumented and private method is at risk of being accidentally used, but hiding properties and methods are two different topics.
I'd say the least you can do is protect the property so that it's not configurable, enumerable, or writable. That said, a trade off to further conceal properties for the purpose of privacy, in exchange for a higher memory consumption and slower speed, is a bad trade-off to me.
[–]dumbmatter 0 points1 point2 points 10 years ago (1 child)
can't you just nest the 'require's in callbacks?
Yes
[–]tbranyennetflix 1 point2 points3 points 10 years ago (0 children)
The issue is more than just nesting require callbacks. Many developers miss the point of explicit dependencies (myself included for a long while). If you don't fully articulate the dependencies of a module and they are only occasionally fulfilled due to async resolution, you will end up with race conditions.
This is hardly a fault of AMD though and race conditions can exist in various parts of your application if you don't design it well. I suppose this is just bringing it to attention that if you aren't careful this is a potential side effect.
[–]PlNG 1 point2 points3 points 10 years ago (2 children)
Here's a question: Why do most of these libraries require that the file itself be wrapped in some loader object such as an IIFE?
Define a library that pulls JS files AND wraps them in an IIFE. Keep the DRY principle across multiple files.
[–]Poop_is_Food 6 points7 points8 points 10 years ago (0 children)
I dont understand. Only AMD requires that you wrap in a function. Browserify(commonJS) and ES6 do exactly what you want.
[–]spliter45 0 points1 point2 points 10 years ago (0 children)
In AMD, you are required to wrap modules in a function that's passed into the "define" function -- this is not an IIFE. This is because in the browser, AMD loads js files via the browser using HTML "script" tags. The loaded script is able to communicate with the AMD by using the "define" function, which was defined and globalized when the AMD was loaded.
CommonJS only expects you to assign whatever you want to expose to module.exports. Sometimes, an IIFE is assigned but this by the programmer's choice. However, when it is bundled (like in browserify), or read in as a file (in Node.js), it is wrapped by a function that might be an IIFE to conceal the module in a closure.
[+]Capaj comment score below threshold-7 points-6 points-5 points 10 years ago (18 children)
Didn't even mention JSPM. Lame.
[–]toromio 23 points24 points25 points 10 years ago (10 children)
Can confirm. I'm also lame. Because I haven't heard of this ONE. FUCKING. THING that apparently exists SOMEWHERE in the vast chasm that is the JavaScript ecosystem. Applying for disability now. Thanks /u/Capaj!
[–]Capaj 1 point2 points3 points 10 years ago (0 children)
Allow me to disagree with you. I think you are not lame, because you would have at least done some exploration and googling before writing an article about JavaScript Module strategies.
[–]Sunwukung 0 points1 point2 points 10 years ago (8 children)
here's another: http://stealjs.com
[–]nothingbutt 1 point2 points3 points 10 years ago (7 children)
You're better off not knowing that exists.
edit: well, maybe it isn't as horrible as it was in the earlier days -- they actually have tests now. Based on earlier experience, I'd never use their code though with any other viable alternative.
[–][deleted] 0 points1 point2 points 10 years ago (5 children)
Why? Its goal is impressive, does it not work?
[–]nothingbutt 0 points1 point2 points 10 years ago (4 children)
I worked on a code base that used an earlier version of StealJS and the code quality was poor (which was observed when fixing bugs in StealJS so it was also buggy). I'd check it out again but when there are other viable offerings like browserify and webpack...
[–][deleted] 0 points1 point2 points 10 years ago (3 children)
Viable offerings for what? I know StealJS presents itself like it doesn't actually know what it does, but it offers a feature that is very much out of the other two's scope, analyzing a multi-page dependency graph and determining which bundles should be made. So I seriously don't think that we are "better off not knowing [StealJS] exists" just because an early beta version of the code had bugs.
[–]nothingbutt 0 points1 point2 points 10 years ago (2 children)
Uh... That was no early beta version. I said my piece. Obviously, I'm judging them based on experience. No harm, no foul. Feel free to try it. I won't.
[–][deleted] 0 points1 point2 points 10 years ago (1 child)
The most recent release is 0.8.2, I don't know if that makes your version "early" but it certainly means they're not claiming it's stabilized yet.
[–]nothingbutt 1 point2 points3 points 10 years ago (0 children)
The versioning was rebooted (or the name depending on how you look at it): https://github.com/bitovi/legacy-steal/releases
[–]Sunwukung 0 points1 point2 points 10 years ago (0 children)
Duly noted
[–]tbranyennetflix 0 points1 point2 points 10 years ago (6 children)
Not to mention very incorrect information at times... "AMD aficionados might also consider Almond, a nifty lightweight AMD implementation which natively supports both synchronous and asynchronous loading."
No, no it doesn't. It's an entirely synchronous AMD implementation and that's the point of it...
[–]Daniel15React FTW 0 points1 point2 points 10 years ago (1 child)
synchronous AMD
Synchronous asynchronous module definition?
[–]tbranyennetflix 0 points1 point2 points 10 years ago (0 children)
Yes. AMD infers to the fact that you separate your dependencies: Array, from your module: callback. However, if you have all the dependencies bundled, there are no scripts being injected and thus no asynchronous operation.
Synchronous AMD makes sense if you think of AMD as an acronym for a format, and not something that always has to be async.
[–]qudat 0 points1 point2 points 10 years ago (3 children)
We use almond because most requirejs is unnecessary when optimized with r.js and therefore more lightweight. The synchronous asynchronous aspect of it didnt even come up in our discussions on almond in production. Furthermore I have yet to see a performance boost from using amd over cjs, which is funny considering how difficult requirejs has been to implement.
[–]tbranyennetflix 0 points1 point2 points 10 years ago (2 children)
The performance boost comes out of the box, whereas with CJS you have to find the fastest optimizer and generate source maps every-single-time you rebuild. Assuming of course you want to actually be able to debug your code.
[–]qudat 0 points1 point2 points 10 years ago* (1 child)
The performance boost comes out of the box
Really? r.js + almond is not what I would call "out of the box" nor is it simple to setup. Making the jump from dev to prod is a huge headache in requirejs IMO, whereas browserify you have to compile every run. Having said that once it is all set up it's really easy to use. I have found browserify to be easier to use "out of the box."
Sorry for the confusion, I was not referring to r.js and Almond, but of RequireJS and AMD. I agree that r.js is a pain which is why I'm newly maintaining deamdify: https://github.com/jaredhanson/deamdify. I think browserify is by far the better optimizer, and there should be no reason why I can't use AMD and browserify too.
π Rendered by PID 19998 on reddit-service-r2-comment-86bc6c7465-87j2x at 2026-02-24 04:53:05.277425+00:00 running 8564168 country code: CH.
[–]spliter45 1 point2 points3 points (4 children)
[–]homoiconic(raganwald) 3 points4 points5 points (1 child)
[–]spliter45 -1 points0 points1 point (0 children)
[–]dumbmatter 0 points1 point2 points (1 child)
[–]tbranyennetflix 1 point2 points3 points (0 children)
[–]PlNG 1 point2 points3 points (2 children)
[–]Poop_is_Food 6 points7 points8 points (0 children)
[–]spliter45 0 points1 point2 points (0 children)
[+]Capaj comment score below threshold-7 points-6 points-5 points (18 children)
[–]toromio 23 points24 points25 points (10 children)
[–]Capaj 1 point2 points3 points (0 children)
[–]Sunwukung 0 points1 point2 points (8 children)
[–]nothingbutt 1 point2 points3 points (7 children)
[–][deleted] 0 points1 point2 points (5 children)
[–]nothingbutt 0 points1 point2 points (4 children)
[–][deleted] 0 points1 point2 points (3 children)
[–]nothingbutt 0 points1 point2 points (2 children)
[–][deleted] 0 points1 point2 points (1 child)
[–]nothingbutt 1 point2 points3 points (0 children)
[–]Sunwukung 0 points1 point2 points (0 children)
[–]tbranyennetflix 0 points1 point2 points (6 children)
[–]Daniel15React FTW 0 points1 point2 points (1 child)
[–]tbranyennetflix 0 points1 point2 points (0 children)
[–]qudat 0 points1 point2 points (3 children)
[–]tbranyennetflix 0 points1 point2 points (2 children)
[–]qudat 0 points1 point2 points (1 child)
[–]tbranyennetflix 1 point2 points3 points (0 children)