The problem background

An Angular4 project failed to connect to the SDK because the console reported undefined

Introduce methods

import sa from 'sa-sdk-javascript';
sa.init({
    server_url: 'https://xxx.com';
});   
Copy the code

Final solution

import * as sa from 'sa-sdk-javascript';
sa.init({
    server_url: 'https://xxx.com';
});   
Copy the code

What’s the difference between these two introductions? Let’s do an example

exporter.js

export default {
  one: "One".two: "Two".three: "Three"};export var a = 'a';
Copy the code

importer.js

// Has 3 props ['one', 'two', 'three']
import anyname from './exporter';

// Has 2 props ['default', 'a'].
import * as allExports from './exporter';
import {one} from './exporter';
import two from './exporter';

console.log(anyname);
console.log(allExports);
console.log(one);
console.log(two);
Copy the code

The output is as follows

{one: "One".two: "Two".three: "Three"}
one: "One"
three: "Three"
two: "Two"
__proto__: Object


a: (...).default: {one: "One".two: "Two".three: "Three"}
Symbol(Symbol.toStringTag): "Module"
__esModule: trueGet a: ƒ ()__proto__: Object


undefined


{one: "One".two: "Two".three: "Three"}
one: "One"
three: "Three"
two: "Two"
__proto__: Object
Copy the code

This is an example of success and an example of failure before that

importer.js

// Has 3 props ['one', 'two', 'three']
import defaultExport from './exporter';

// Has 2 props ['default', 'a'].
import * as allExports from 'exporter';

console.log(defaultExport)
console.log(allExports)
Copy the code

Run node importer. Js directly

import defaultExport from './exporter'; ^^^^^^^^^^^^^ SyntaxError: Unexpected identifier at new Script (vm.js:74:7) at createScript (vm.js:246:10) at Object.runInThisContext (vm.js:298:10) at Module._compile (internal/modules/cjs/loader.js:646:28) at Object.Module._extensions.. js (internal/modules/cjs/loader.js:689:10) at Module.load (internal/modules/cjs/loader.js:589:32) at tryModuleLoad (internal/modules/cjs/loader.js:528:12) at Function.Module._load (internal/modules/cjs/loader.js:520:3) at Function.Module.runMain (internal/modules/cjs/loader.js:719:10) at startup (internal/bootstrap/node.js:228:19)Copy the code

What makes it work? It runs in an Angular project, and the key is Babel

As for the understanding of import and export, it is not deep. Learn the syntax of Module in ES6

Here are the key words notes

I. HistoryjsThere is no module system

Js’s original design had no concept of modules at all

Defect: Inability to break large programs into small interdependent files (modules) and put them together in a simple way

In fact this is for engineering defects, the reason for the large program into dependent small module, is for the sake of different functions can be separated for development and maintenance, like small system, and finally rebuilt in a simple way is because the program run does not focus on how a more complex, as long as the program runs through can run, Divide-and-conquer is simply a way for humans to help themselves understand and process vast programs.

There is no harm without comparison: ruby, a scripting language, has its own require, Python has its own import, and even CSS has its own @import. Js before ES6 is humiliated by comparison

Second,CommonJSandAMDIt was before es6communityThe solution

CommonJS for servers, AMD for browsers

Third, es6 fromLanguage standardModule functions are realized on the level, and the implementation is quite simple

Nice, raised his head from then on

Es6’s module capabilities can replace CommonJS and AMD as a universal module solution

Fourth, es6 module design idea is as far as possiblestatic(Another new concept)

Statically means that module dependencies and input and output variables can be determined at compile time

Five, the contrastCommonJSAdvantages such asCommonJSThe module is an object, and you must look for object properties when entering

It is very stiff

I feel it is necessary to take a look at the history of CommonJS and AMD

  • CommonJS specification
  • CommonJS specification for Webpack Chinese documentation

Six, about staticCommonJSComparison with es6 modules

CommonJS

/ / CommonJS module
let { stat, exists, readFile } = require('fs');

/ / is equivalent to
let _fs = require('fs');
let stat = _fs.stat;
let exists = _fs.exists;
let readfile = _fs.readfile;
Copy the code

While the first line looks similar to the es6 module we’re using today, there are actually two key differences

  1. The above operation is actualThe overall loadthefsModule, and just use the three methods in it
  2. The above action is in the programRun time loadingBecause this object is only available at runtime (and therefore cannot be done at compile time)The static optimization)

Es6 module

/ / ES6 module
import { stat, exists, readFile } from 'fs';
Copy the code
  1. Es6 modules are not objects, but passexportThe commandexplicitSpecify the output code, then passimportThe command input
  2. The above operation only loads these three methods. Other methods are not loadedLoad at compile time (statically loaded)

This is the advantage achieved from the language standard level (a shame), simply add two built-in keywords, through the command to complete the pre-compile module transmission declaration, the community solution can only curve save the country.

Seven, aboutexportThe command

  1. A module is an independent file
  2. All variables inside the file are not available outside the file
  3. External read module variables must be usedexportOutput the variable

For example,

// profile.js
export var firstName = 'Michael';
export var lastName = 'Jackson';
export var year = 1958;
Copy the code

Another way to write it

// profile.js
var firstName = 'Michael';
var lastName = 'Jackson';
var year = 1958;

export { firstName, lastName, year };
Copy the code

Output method or class

export function multiply(x, y) {
  return x * y;
};
Copy the code
export class multiply(x.y) {
  return x * y;
};
Copy the code

Rename the output

function v1() {... }function v2() {... }export {
  v1 as streamV1,
  v2 as streamV2,
  v2 as streamLatestVersion // The same output object (variable, class, method) can be renamed multiple times
};
Copy the code

Matters needing attention

  1. exportThe command specifies the external interface, which must establish a one-to-one relationship with variables in the module (interface name and variables in the module one-to-one).
  2. You cannot output the value of a variable directly, but should output it as an interface

counter-examples

// Output the value directly
export 1;

var m = 1;
// Print the value of the variable directly
export m;
Copy the code

Positive solution

// Print the declared variable directly
export var m = 1;

// Declare variables first, then output variables
var m = 1;
export {m};

// Declare the variable first, then print the variable as an alias
var n = 1;
export {n as m};
Copy the code

The above three types of scripts are exported through interface M, through which other scripts obtain their internal values

The characteristics of

The interface output by the export statement is dynamically bound to its corresponding value, through which the real-time value inside the module can be obtained

For example,

export var foo = 'bar';
setTimeout(() = > foo = 'baz'.500);
Copy the code

The value of foo starts with bar and becomes baz after 0.5 seconds

This feature contrasts with CommonJS, where modules output a cache of values

Matters needing attention

  1. exportIt can appear anywhere in the module, but at the top of the module
  2. If in theBlock-level scopeAn error is reported because being in a conditional block prevents static optimization and defeats the purpose of the ES6 module

Eight, aboutimportThe command

  1. importThe command accepts a pair of curly braces specifying what to import from another moduleThe variable name– see case 1
  2. The variable name in braces must match that of the imported module interfaceThe same name
  3. If you want to rename an imported variable, you can use it at import timeasRename it — see example 2
  4. importThe command input variables areread-onlyThe properties of a variable can be overwritten, but this can be dangerous, affecting other places where the module is introduced — see Example 3 (Objects that are similar to const declarations can change their internal properties, modules)exportThe output interface is equivalent to an object.

Case 1

// main.js
import { firstName, lastName, year } from './profile.js';
function setName(element) {
  element.textContent = firstName + ' ' + lastName;
}
Copy the code

Case 2

import { lastName as surname } from './profile.js';
Copy the code

Example 3

import {a} from './xxx.js'
a.foo = 'hello'; // It is valid
Copy the code

Introducing way

  1. It can be a relative path or an absolute path
  2. .jsSuffixes can be omitted
  3. Import module name without pathThe configuration fileTells the JS engine the location of the module

Matters needing attention

  1. importHas a promotion effect that will be promoted to the head of the entire module first executed (essentially becauseimportThe command is executed at compile time, before the code runs) — see Example 1
  2. Due to theimportStatically executed, so cannot be usedexpressionandvariableBecause these are all inThe runtimeTo get a syntactic interface to the result — see Example 2

Case 1

foo();
// Although the location is below, the execution precedes the foo() call
import { foo } from 'my_module';
Copy the code

Case 2

/ / an error
import { 'f' + 'oo' } from 'my_module';

/ / an error
let module = 'my_module';
import { foo } from module;

/ / an error
if (x === 1) {
  import { foo } from 'module1';
} else {
  import { foo } from 'module2';
}
Copy the code

Matters needing attention

  1. importThe statement executes the loaded module
  2. Repeat the same sentence many timesimportThe statement is executed only once (singleton mode) — see Example 1
  3. Currently, throughbabelTranscoding,CommonJSThe modulerequireCommands andes6The moduleimportCommands can coexist, but are not recommended becauseimportinStatic analysisPhase execution, the earliest execution in a module, may makerequireStatement does not execute as expected — see example 2

Case 1

import 'lodash';
import 'lodash';
// Only loads once

import { foo } from 'my_module';
import { bar } from 'my_module';

/ / is equivalent to
import { foo, bar } from 'my_module';
// Only loads once
Copy the code

Case 2

require('core-js/modules/es6.symbol');
require('core-js/modules/es6.promise');
// Execute first
import React from 'React';
Copy the code

Ix. Loading the module as a whole

way

Use an asterisk (*) to specify an object on which all module output values are loaded

// circle.js

export function area(radius) {
  return Math.PI * radius * radius;
}

export function circumference(radius) {
  return 2 * Math.PI * radius;
}
Copy the code

One by one to load

// main.js

import { area, circumference } from './circle';

console.log('Circle area:' + area(4));
console.log('Circumference:' + circumference(14));
Copy the code

The overall load

import * as circle from './circle';

console.log('Circle area:' + circle.area(4));
console.log('Circumference:' + circle.circumference(14));
Copy the code

Pay attention to the point

The object in which the module is loaded as a whole can be analyzed statically and cannot be changed at run time

import * as circle from './circle';

// The following two lines are disallowed
circle.foo = 'hello';
circle.area = function () {};
Copy the code