篇の文章はあなたにES 6のモジュール化をわかるように手伝います.
9513 ワード
先端モジュール化は先端工程化の礎石である.現在、大先端時代においてはモジュールの運用はさらに進んでいますが、将来を見据えて、es 6に提出されたimportとexportの形式は統一前後のモジュール化されているようです.
モジュール化の概要
ES 6のモジュール化を学ぶ前にまず復習します.前に出たモジュール化を比較的によく使うのは、CommunJS、AMD、CMDの3つの規定です.
それらの特徴と相互の違いは: Common JSはサーバーに適用されます.書き方は です. AMD(Aynchronous Module Definition)は、非同期ローディングモジュールであり、ブラウザ(requireJsがこの仕様を適用した)に多く使われています. CMD(Common Module Definition)は近くに依存して、使う時またrequire(seajs推奨の規範)を使って、書き方は:
AMDは前置に依存しています.jsはモジュールに依存していますか?
CMDは近くに依存しています.開発者は依存する時にrequireを使うことができます.しかし、jsプロセッサにとっては、コードを文字列解析にして初めて、どのモジュールに依存しているか、すなわち性能を犠牲にして開発の便利さを得ることができます.
ES 6のモジュール設計思想はできるだけ静的になり、コンパイル時にモジュールの依存関係が確定できるようになります.
Common JSとES 6モジュールを比較する:
ES 6モジュール化の文法規範
厳格モード
ES 6モジュールでは、自動的に厳格なモードを採用します.規定:変数は、先に を宣言しなければなりません.関数パラメータは同じ名前の属性を持つことができません. は を使用できません.読み取り専用属性に対して値を割り当て、 .は、変数 だけ削除できます. . を再割り当てすることができません. 禁止 を指す.予約字を追加します.static、interface、protectedなどです. 注意:ES 6モジュールで、トップレベル
exportコマンド
最初の種類: export文が出力するインターフェースは、対応する値の参照、すなわち動的バインディング関係であり、このインターフェースを通じてモジュール内部のリアルタイムの値を取得することができる.Common JS仕様を比較します.CommunJSモジュールが出力するのは値のキャッシュです.ダイナミックアップデートは存在しません. exportコマンドは、モジュールの最上階にあると規定していますが、ブロックレベルのスコープ内に出現すると、エラーが発生します.importは同じです. importコマンド
最初の種類:
を使用してオブジェクトを指定できます.出力値はすべてこのオブジェクトにロードされます.
export defaultコマンドはモジュールのデフォルト出力になります.
前に述べたように、requireはダイナミックローディングであり、使う時にまたrequireを使うことができます.importは静的に実行され、コードの最上階にあるだけで、ブロックレベルの作用領域に存在してはいけない.これは、importがAMDの欠点のような運転中に実行できなくなります.そこで、import()関数を導入し、Nodeのrequire関数(CommunJS)に似ていますが、非同期的な負荷を実現する提案があります.
定義:import()関数はimportと同じパラメータを受信し、Promiseオブジェクトに戻り、取得した値をthen法のコールバックパラメータとしてロードする.
importロードCommon JSモジュール importコマンドを使用してCommunJSモジュールをロードします.Nodeは自動的にmodule.export属性をモジュールのデフォルト出力とします.つまり、export default と同じです. CommunJsモジュールは実行時に出力インターフェースが確定されますので、importコマンドでCommonJSモジュールをロードする場合は、全体入力(*)のみ使用できます. requireロードES 6モジュール requireコマンドがES 6モジュールをロードすると、すべての出力インターフェースが入力対象の属性となります. Common JSを比較
新しいファンがあっても、古い愛を忘れてはいけません.CommunJSとES 6のモジュール化との違いを引き続き比べて、ES 6のモジュール化の特性を理解してみましょう.
出力の違い
Common JSモジュールが出力するのは値のコピーで、ES 6が出力するのは値の参照です.
ロード原理
CommunJSモジュールはスクリプトファイルに対応しています.requireコマンドはモジュールをロードするたびにスクリプト全体を実行し、オブジェクトを生成します.このオブジェクトが生成されると、後で同じrequireコマンドを実行しても、直接にキャッシュに値を取ります.つまり、Common JSモジュールは何回ロードしても、最初のロード時に一回だけ実行され、その後再ロードする時に初めて実行された結果に戻ります.手動でシステムキャッシュをクリアしない限り、.
ループローディング Common JSモジュールがループローディングに遭遇したことにより、コードが全部実行された値ではなく、現在実行されている部分の値が返ってきます. Common JSは、動的参照ではなく、出力値のキャッシュに入力される. 比較:ES 6モジュールは動的参照であり、変数はキャッシュされません.
モジュール化の概要
ES 6のモジュール化を学ぶ前にまず復習します.前に出たモジュール化を比較的によく使うのは、CommunJS、AMD、CMDの3つの規定です.
それらの特徴と相互の違いは:
var clock = require('clock.js')
clock.start();
上記の例によれば、clock
の呼び出しはclock.js
がロード成功を要求するのを待たなければならない.言い換えれば、同期動作である.これはまた、クライアントではなくサービス端末に広く適用されることになる.require([module],callback);
// eg
require(['clock.js'],function(clock){
clock.start();
})
非同期的なロードを実現し、ブラウザの「仮死」問題を回避しているが、最初からすべての依存を書き出すのは論理的な順序に合わないという欠点もある.じゃ、CommunJSのように使う時にrequireを使って、非同期ロードをサポートして実行してもいいですか?define(function(require,exports,module){
var clock = require('clock.js');
clock.start();
})
AMDとCMDの違いは、依存モジュールの実行タイミングが異なり、ローディング処理方式が異なるのではなく、両方とも非同期ローディングモジュールである.AMDは前置に依存しています.jsはモジュールに依存していますか?
CMDは近くに依存しています.開発者は依存する時にrequireを使うことができます.しかし、jsプロセッサにとっては、コードを文字列解析にして初めて、どのモジュールに依存しているか、すなわち性能を犠牲にして開発の便利さを得ることができます.
ES 6のモジュール設計思想はできるだけ静的になり、コンパイル時にモジュールの依存関係が確定できるようになります.
Common JSとES 6モジュールを比較する:
// CommonJS
let { start, exists, readFile } = require('fs')
//
// let _fs = require('fs')
// let start = _fs.start, exists = _fs.exists, readFile = _fs.readFile
// ES6
import { start, exists, readFile } from 'fs'
上記の例では、Common JSは実質的に全体ローディングfsモジュールで_fs
オブジェクトを生成した後、オブジェクトからそれぞれ3つの方法を読み出して、「実行時ローディング」と呼ぶ.ES 6モジュールは3つの方法をロードします.「コンパイル時ローディング」といいます.ES 6モジュール化の文法規範
厳格モード
ES 6モジュールでは、自動的に厳格なモードを採用します.規定:
with
delete
は属性を削除してはいけない.直接エラーを報告するdelete prop
を削除することができません.属性delete global[prop]
eval
は、外層作用領域に変数を導入しないeval
およびarguments
は、値arguments
は自動反応関数パラメータの変化がありません.this
は、グローバルthis
はundefined
、使われるべきではない.exportコマンド
最初の種類:
export var a = '123';
export const _b = '2323'
export let c = '2222'
第二種類:var a = '123';
const _b = '2323'
let c = '2222'
export {a, _b, c}; //
第三の種類(第二のキーワードにasキーワードを加えて名前を変えます)var a = '123';
const _b = '2323'
let c = '2222'
export {
a as stream1,
_b as stream2,
c as stream3};
注意:最初の種類:
import {a, _b ,c} from './profile'
第二種類:import {stream1 as firstVal} from './profile'
importは静的な実行であり、式、変数、if構造は適用できません.if(x == 1){
import { foo } from 'module1'
}else{
//...
}
import文はSingletonモードである.foo
およびbar
は2つの文にロードされているが、対応するのは同じmy_module
の例である.import { foo } from './module1'
import { bar } from './module1'
//
import {foo,bar} from './module1'
モジュール全体のロードを使用してオブジェクトを指定できます.出力値はすべてこのオブジェクトにロードされます.
import * as circle from './module1'
circle.foo();
circle.bar();
モジュール全体のロード先のオブジェクトは静的に分析できますので、実行時の変更は許可されません.import * as circle from './module1'
//
circle.foo = 123;
circle.bar = function(){}
標準出力export defaultコマンドはモジュールのデフォルト出力になります.
// module2.js
export default function(){
console.log('123')
}
//
function a(){
console.log('123')
}
export {a as default};
importコマンドは、匿名関数に任意の名前を割り当てることができます.import defaultFn from './module2'
//
import {default as defaultFn} from './module2'
exportとimportの複合書き方export { foo, bar} from 'my_module';
//
import {foo,bar} from 'my_module';
export{foo,bar};
export {es6 as default} from './someModule'
//
import {es6} from './someModule'
export default es6;
import()方法前に述べたように、requireはダイナミックローディングであり、使う時にまたrequireを使うことができます.importは静的に実行され、コードの最上階にあるだけで、ブロックレベルの作用領域に存在してはいけない.これは、importがAMDの欠点のような運転中に実行できなくなります.そこで、import()関数を導入し、Nodeのrequire関数(CommunJS)に似ていますが、非同期的な負荷を実現する提案があります.
定義:import()関数はimportと同じパラメータを受信し、Promiseオブジェクトに戻り、取得した値をthen法のコールバックパラメータとしてロードする.
const main = document.querySelector('main')
import(`./section-modules/${someVariable}.js`)
.then(module => {
module.loadPageInto(main);
})
.catch(err => {
main.textContext = err.message;
})
// :
import('./module1.js')
.then(({default:defaultFn,foo,bar}) => {
console.log(defaultFn)
})
// async
async function main() {
const myModule = await import('./myModule.js');
const {export1, export2} = await import('./myModule.js');
const [module1, module2, module3] =
await Promise.all([
import('./module1,js'),
import('./module2.js'),
import('./module3.js')
])
}
main();
異なる仕様間のロードimportロードCommon JSモジュール
// a.js
module.exports = {
foo: 'hello',
bar: 'world'
}
// import
export default {
foo: 'hello',
bar: 'world'
}
import {readfile} from 'fs' // 'fs' CommonJS
//
import * as express from 'express'
const app = express.default();
// es.js
let foo = {bar : 'my-default'};
exxport default foo;
foo = null;
// cjs.js
const es_namespace = require('./es')
console.log(es_namespace.default);// {bar:'my-default'}
新しいファンがあっても、古い愛を忘れてはいけません.CommunJSとES 6のモジュール化との違いを引き続き比べて、ES 6のモジュール化の特性を理解してみましょう.
出力の違い
Common JSモジュールが出力するのは値のコピーで、ES 6が出力するのは値の参照です.
// lib.js
let num = 3;
function changeNum() {
num = 4;
}
module.exports = {
num: num,
changeNum: changeNum,
};
//main.js
var mod = require('./lib.js')
console.log(mod.num); // 3
mod.changeNum();
console.log(mod.num); // 3
これは、mod.numが元のタイプの値であるため、キャッシュされます.関数を作成することで、内部修正後の値を得ることができます.// lib.js
let num = 3;
function changeNum() {
num = 4;
}
module.exports = {
get num(){
return num
},
changeNum: changeNum,
};
//main.js
var mod = require('./lib.js')
console.log(mod.num); // 3
mod.changeNum();
console.log(mod.num); // 3
比較ES 6モジュール:// lib.js
export let num = 3;
export function changeNum() {
num = 4;
}
//main.js
import {num,changeNum} from './lib.js'
console.log(num); // 3
changeNum();
console.log(num); // 4
Common JSの循環ローディングロード原理
CommunJSモジュールはスクリプトファイルに対応しています.requireコマンドはモジュールをロードするたびにスクリプト全体を実行し、オブジェクトを生成します.このオブジェクトが生成されると、後で同じrequireコマンドを実行しても、直接にキャッシュに値を取ります.つまり、Common JSモジュールは何回ロードしても、最初のロード時に一回だけ実行され、その後再ロードする時に初めて実行された結果に戻ります.手動でシステムキャッシュをクリアしない限り、.
ループローディング
// a.js
exports.done = false;
var b = require('./b.js'); // 1. a.js , b.js ; b.js ,b:{done:true}
console.log(' a.js ,b.done=%j',b.done); // 5. ' a.js ,b.done=true'
exports.done = true;
console.log('a.js ') // 6. 'a.js '
// b.js
exports.done = false;
var a = require('./b.js') // 2. a:{done:false}
console.log(' b.js ,a.done=%j',a.done); // 3. ' b.js ,a.done=false'
exports.done = true;
console.log('b.js ') // 4. 'b.js ', a.js
// main.js
var a = require('./a.js');
var b = require('./b.js');
console.log(' main.js ,a.done=%j,b.done=%j',a.done,b.done); // 7.' main.js ,a.done=true,b.done=true'
上のコードを見ることができます.第一に、b.jsでは、a.jsは実行されていません.第二に、main.jsが第二行まで実行された場合は、b.jsは再実行されません.キャッシュされたb.jsの実行結果を出力します.即ち、その第四行:exports.done = true
まとめてみます// a.js
import {bar} from './b.js';
export function foo(){
console.log('foo')
bar();
console.log(' ')
}
foo();
// b.js
import {foo} from './a.js' // CommonJS, undefined
export function bar(){
console.log('bar')
if(Math.random() > 0.5){
foo();
}
}
// :foo bar
// : foo bar foo bar