Module understanding and use

The modular design idea of ​​ES6 is static, that is to say, the dependencies of modules and the variables of output and output are determined at compile time. Both CommonJS and AMD modules are determined at runtime. The ES6 module is not an object, but displays the specified output code through export, and then enters it through the import command.

// module input
import { start,address } from 'util'

The above module input loads two methods, even if there are other methods in the util module, it will not be loaded, only the two methods introduced above will be loaded. This loading is called "compile-time loading" or static loading.

It should be noted that ES6 modules automatically adopt strict mode, regardless of whether "use strict" is added to the header or not, strict mode will be enabled. The strict mode restrictions are as follows:

1. Variables must be declared before use
2. Function parameters cannot have attributes with the same name, otherwise an error will be reported
3. You cannot use the with statement
4. You cannot assign a value to a read-only attribute, otherwise an error will be reported
5. The prefix 0 cannot be used to represent octal numbers, otherwise an error will be reported
6. Undeletable attributes cannot be deleted, otherwise an error will be reported
7. The variable delete prop cannot be deleted, an error will be reported, and the property can only be deleted delete global[prop]
8. eval will not introduce variables in its outer scope
9. eval and arguments cannot be reassigned
10. arguments will not automatically reflect changes in function parameters
11. Cannot use arguments.callee
12. Cannot use arguments.caller
13. Forbid this to point to the global object
14. You cannot use fn.caller and fn.arguments to get the stack of function calls
15. Added reserved words (such as protected, static and interface)

export and import commands

The module is mainly composed of export and import. export specifies the external interface of the module, and import is used to import the functions provided by the module.
module export

// util module
// type
function type(a){
    return typeof a
}
// calculate
function sum(a,b) {
    return a * b 
}
// Determine whether it is an array
function isArray(a) {
    return a instanceof Array
}
export { type,sum }  // export on demand

module import

import {  type,sum } from './util'
let num = sum(10,5)
console.log(num) // 50

The above two methods are exported in an optional way, that is to say, when import imports a module, only the method exported by export will be loaded, and other methods will not be loaded by import, and the util module imported by import can be imported on demand. Only the modules you need can be used, and other modules that are not introduced will not be loaded, which is the benefit of static loading.

In addition to the on-demand export of export { xxx,xxx }, ES6 also provides the default export of export default and the default export method. When import ing, it does not need to follow the export name, and you can customize the name to receive the export method.

// util module
// calculate
function sum(a,b) {
    return a * b 
}
// Determine whether it is an array
function isArray(a) {
    return a instanceof Array
}

export default sum // export by default
import aaa from './util'  // The name can be customized when importing
let num = aaa(10,5)
console.log(num) // 50

In fact, this default is a variable called default. This variable can be named arbitrarily. When import ing, any name can match the method exported by default.

On-demand and default exports
export { xxx,xxx } and export default default export can be used at the same time

// util module
function type(a){
    return typeof a
}

function sum(a,b) {
    return a * b 
}

function isArray(a) {
    return a instanceof Array
}

export { type,sum }
export default isArray
// import
import { type,sum }from './util'  
import aaa from './util'  

The overall loading of the module

The above export methods are all corresponding methods in the loading module. The overall loading of the module should use *, that is, loading all. The syntax is as follows

import * as util from './util';
// use in the page
let num = util.sum(10,5)
console.log(num)  // 50

This way of writing is to load the module as a whole, specify an object with *, and all output values ​​​​are loaded on this object. Obtain the corresponding method through the object.method name.
It should be noted that ES6 modules are statically analyzed, and changes to modules are not allowed, so the following writing is not allowed:

util.sum = 'hello' // report error
util.sum = function () {} // report error

module inheritance

Modules can also be inherited, assuming that module A inherits module B

// A module
function sum(a,b) {
    return a * b 
}

function isArray(a) {
    return a instanceof Array
}

export * from 'B'  // Output all properties and methods of module B, ignoring the default method in the module
export { sum } 
export default isArray

The export * command will ignore the default method of the B module, because the A module has its own default method inside.

module renaming

// util module
export { sum as s }
// page
import { s } from './util'  // Introducing named methods

The module introduces import() on demand

Under normal circumstances, import needs to be introduced at the top level of the page, and the priority of import execution is the highest, for example:

let s = sum(10,5)
import { sum } from './util' 

The above writing method is allowed, the program will execute the introduction of import, and then execute let s = sum(10,5), but this writing method will import the module by default, and it is imported at the top level.
es6 provides a dynamic import function: import(), which will be imported when the program executes to the statement, and it is executed synchronously. import() returns a Promise, so the then method and async-await can be used.
Promise writing

import('./util.js')
.then(el=>{
   console.log(el.t(100));  // number
   console.log(el.sum(10,5));  // 50
})

async-await writing method

async function getImport(){
      let { sum } = await import('./util.js')
      console.log(sum(2,8));
}
getImport()  // 16

It can also be obtained by deconstruction

import('../module/import.js')
.then(({sum})=>{
     console.log(sum(20,5));  // 100
})

If the module is exported by default, in fact default is a key name

import('../module/import.js')
.then((e)=>{
   console.log(e.default([1,2,3]));  // true
})

default can also be imported in a named form (aliased)

import('../module/import.js')
.then(({default : isA})=>{
     console.log(isA([1,2,3]));  // true
})

import.meta

When using a module, sometimes you need to know the information of the module itself (such as the path of the module), the import command adds a new meta attribute import.meta, which can return the information of the current module.
Note: import.meta can only be used within the module, and an error will be reported if used outside the module

// util module
function sum(a,b) {
    return a * b 
}

function getMeta(){
    return import.meta  // Get the meta information of the current module
}

export { sum,getMeta }
// console.log(import.meta); // import.meta can only be used within the module, and an error will be reported if used outside the module
import('./util.js')
.then(el=>{
      console.log(el.getMeta());  // {url: 'http://127.0.0.1:5500/module/import.js', resolve: ƒ}
})

Case source code: https://gitee.com/wang_fan_w/es6-science-institute

If you think this article is helpful to you, please light up the star

Tags: Front-end Javascript Vue.js ecmascript-6

Posted by b-real on Sun, 19 Feb 2023 19:18:51 +1030