What is require, import and export, in JavaScript?
Ideally, developers should only concern about core business logic. For other modules, developers just need to load and use them.
Unfortunately, because JavaScript does not natively support class
, it is not a modular programming language, like Java, C#.
1. Function:
Function is everything. Just simply put all relative functions and their status together, it is a module.
function method1() {
}
The problem is functions are contaminatin the global scope.
2. Object:
So, some smart people use a object to hold function.
var moduleObject = new Module({
_state: 'default',
method1: function() {
}
})
The problem for that is, _state
is accessible and expose to the public, by doing moduleObject._state
.
3. IIFE:
To solve that problem, IIFE (Immediately-Invoked Function Expression) is used to stop that.
var moduleObject = (function () {
var _state = 'default';
var method1 = function () {
return 'new state'
}
return {
result1: method1
}
})()
This will result undefined
if do moduleObject._state
again. Instead, module only expose result1
to the public.
4. CommonJS
In Nodejs, there is a global function require()
to load modules.
var Koa = require('koa')
5. AMD & Require.js
Thanks to CommonJS successfully modularized server side JavaScript. People would think about: how about client side JavaScript?
AMD (Asynchronous Module Definition), it loads module asynchronously. So loading modules does not block the code runtime.
All codes having dependency on modules, will wait until all dependencies are loaded. Then the callback will be executed.
If there are multiple dependencies, we need to define()
it in the module.
define('moduleName', ['Dependency1'], function (Dependency1) {
function foo() {
Dependency1.doTask()
}
return {
foo: foo
}
})
Then, when some code require()
the definition of module, it also requires its dependencies.
require([module], fn(module) {
module.doTask()
})
Compare to previous CommonJS:
var module = require('module')
module.doTask()
This way will block browser’s execution.
6. CMD
CMD (Common Module Definition) is more incline of lazy loading. Require the module dependency when use it.
The definition is the same like AMD:
define('moduleName', [Dependency1], function (Dependency1) {
function foo() {
Dependency1.doTask()
}
return {
foo: foo
}
})
7. AMD vs. CMD
The biggest difference is not how to load modules, but when to execute modules.
AMD load modules before hand. CMD load modules when it needed.
8. ES6
From ES6, module has been standardized.
export
defines how module get exposed to other modules.
- named export: can export multiple modules.
export {variable1, variable2 as name2 ...}
- default export: can only export one module.
export default expression
export {expression as default}
import
defines how to declare other modules inside module
- named import:
import * as name from 'module-name'
import { member1, member2 as aliasMember2 }from 'module-name'
- default import:
import name from 'module-name'
import $, { each, map } from 'jquery'; // mixed
Bear in mind, import
is readonly. But imported object’s members are writable (it is not recommended to write it though).
9. exports
and module.exports
Every node module has a module
object. Every module
object has a member exports
. And module.exports
will be returned at the end. So when we try to export the module members, we only need to mount members onto module.exports
.
module.exports.a = 123
module.exports = {
a: 123
}
10. Precedence
In RequireJS, return
has top precedence, module.exports
is after, exports
is the lowest. No matter the order of lines of code.
define(function(){
module.exports = {} // Medium (even though it runs first)
return {} // Highest
})