Categories
Dev

require, import and export

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.

  1. named export: can export multiple modules.
export {variable1, variable2 as name2 ...}
  1. default export: can only export one module.
export default expression
export {expression as default}

import defines how to declare other modules inside module

  1. named import:
import * as name from 'module-name'
import { member1, member2 as aliasMember2 }from 'module-name'
  1. 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
})