關於import和require的一點理解

基本概念

require用於讀取並執行js文件, 並返回該模塊的exports對象, 若無指定模塊, 會報錯。 Node使用CommonJS模塊規範, CommonJS規範加載模塊是同步的, 只有加載完成, 才能執行後續操做。css

import用於引入外部模塊, 其餘腳本等的函數, 對象或者基本類型。 import屬於ES6的命令, 它和require不同, 它會生成外部模塊的引用而不是加載模塊, 等到真正使用到該模塊的時候纔會去加載模塊中的值。es6

靜態編譯和動態編譯

requir動態態編譯

第一次加載某個模塊時, Node會緩存該模塊, 後續加載就從緩存中獲取。promise

require是運行時調用,因此require理論上能夠運用在代碼的任何地方。瀏覽器

//example.js
module.exports = {
    say: 'hi'
}

//main.js
require('./example').say = 'hello'
const test = require('./example').say
console.log(test)       //hello
複製代碼

上面的test從新引入example, 但它的say屬性仍是上面的hello, 說明並無重新加載example模塊, 而是從緩存中獲取的該模塊, 因此say屬性不是hi緩存

import靜態編譯

ES6模塊的編譯: import模塊時只是生成引用, 等到須要時纔去取值, 因此不存在緩存的問題, 並且模塊裏的變量, 綁定其所在的模塊。babel

import是編譯時調用,雖然import命令具備提高效果,會提高到整個模塊的頭部, 但仍是建議放在文件開頭。函數

// base.js
export var foo = 'bar';
setTimeout(() => foo = 'baz change', 500);

// main.js
import { foo } from './base';
console.log(foo); // bar
setTimeout(() => console.log(foo), 600);// baz changed
複製代碼

上面代碼能夠看到, 兩次獲取的foo值是不一樣的, 由於import是動態加載, 能夠感知到base.js中的變化.ui

這樣的設計,能夠提升編譯器效率,可是沒有辦法實現運行時加載。spa

由於require是運行時加載,因此import命令沒有辦法代替require的動態加載功能。prototype

import爲了實現動態加載, 引入了import()函數, 該函數返回一個promise對象。

import(`./xxxx.js`)
  .then(module => {
    ...
  })
  .catch(err => {
    ...
  });
複製代碼

可是, 這樣存在一個問題: 就是可能出現模塊尚未加載完就被調用的狀況, 此時會調用失敗。

// base.js
export var fish;

setTimeout(() => fish = 'fish', 500);


// main.js
import { fish } from './base';

console.log(fish); //undefined
複製代碼

babel對於import的轉碼

由於當前瀏覽器並不徹底支持import, 因此咱們須要經過babel將import轉碼成require。

// es6Test.js
import * as actions from './searchAccount.actions';
import kdbTheme from '../../../common/Dialog/panguTheme.css';
import { createCommonAccount } from './createDialog.actions';

console.log('createCommonAccount###', createCommonAccount);
// babel編譯es6Test.js
/* import * as actions from './searchAccount.actions' */
var _searchAccount = require('./searchAccount.actions'); 

var actions = _interopRequireWildcard(_searchAccount);

/* import kdbTheme from '../../../common/Dialog/panguTheme.css' */
var _panguTheme = require('../../../common/Dialog/panguTheme.css');

var _panguTheme2 = _interopRequireDefault(_panguTheme);

/* import { createCommonAccount } from './createDialog.actions'*/
var _createDialog = require('./createDialog.actions');

console.log('createCommonAccount###', _createDialog.createCommonAccount);

function _interopRequireWildcard(obj) { 
    if (obj && obj.__esModule) { return obj; } 
    else {
        var newObj = {}; 
        if (obj != null) { 
            for (var key in obj) { 
                if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; 
            } 
        } 
        newObj.default = obj; 
        return newObj; 
    } 
}

function _interopRequireDefault(obj) { 
    return obj && obj.__esModule ? obj : { default: obj }; 
}
複製代碼

關於二者的使用

require

  1. require: 函數,用於導入模塊

  2. module.exports: 變量,用於導出模塊

module.exports = ...

exports.xxx = ...

const xxx = require('/xxx')
const {xxx1, xxx2, xxx3} = require('/xxx')

複製代碼

import

  1. import: 導入

  2. export: 導出

import xxx from '/xxx'

import * as xxx from '/xxx'

import {xxx1, xxx2, xxx3} from '/xxx'

export xxx

export {xxx1, xxx2, xxx3}

export default xxx
複製代碼
相關文章
相關標籤/搜索