1. 程式人生 > >ES6新特性:使用export和import實現模組化

ES6新特性:使用export和import實現模組化

  在ES6前, 前端就使用RequireJS或者seaJS實現模組化, requireJS是基於AMD規範的模組化庫,  而像seaJS是基於CMD規範的模組化庫,  兩者都是為了為了推廣前端模組化的工具, 更多有關AMD和CMD的區別, 後面參考給了幾個連結;

   現在ES6自帶了模組化, 也是JS第一次支援module, 在很久以後 ,我們可以直接作用importexport在瀏覽器中匯入和匯出各個模組了, 一個js檔案代表一個js模組;

  現代瀏覽器對模組(module)支援程度不同, 目前都是使用babelJS, 或者Traceur把ES6程式碼轉化為相容ES5版本的js程式碼;

  ES6的模組化的基本規則或特點:

  ES6的模組化的基本規則或特點, 歡迎補充:

    1:每一個模組只加載一次, 每一個JS只執行一次, 如果下次再去載入同目錄下同檔案,直接從記憶體中讀取。 一個模組就是一個單例,或者說就是一個物件;

    2:每一個模組內宣告的變數都是區域性變數, 不會汙染全域性作用域;

    3:模組內部的變數或者函式可以通過export匯出;

    4:一個模組可以匯入別的模組

//lib.js
//匯出常量
export const sqrt = Math.sqrt;
//匯出函式
export function square(x) {
    
return x * x; } //匯出函式 export function diag(x, y) { return sqrt(square(x) + square(y)); } //main.js import { square, diag } from './lib'; console.log(square(11)); // 121 console.log(diag(4, 3)); // 5

    

  下面列出幾種importexport的基本語法:

  第一種匯出的方式:

  在lib.js檔案中, 使用 export{介面} 匯出介面, 大括號中的介面名字為上面定義的變數, import

export是對應的;

//lib.js 檔案
let bar = "stringBar";
let foo = "stringFoo";
let fn0 = function() {
    console.log("fn0");
};
let fn1 = function() {
    console.log("fn1");
};
export{ bar , foo, fn0, fn1}

//main.js檔案
import {bar,foo, fn0, fn1} from "./lib";
console.log(bar+"_"+foo);
fn0();
fn1();

    

  第二種匯出的方式:

   在export介面的時候, 我們可以使用 XX as YY, 把匯出的介面名字改了, 比如: closureFn as sayingFn, 把這些介面名字改成不看文件就知道幹什麼的:

//lib.js檔案
let fn0 = function() {
    console.log("fn0");
};
let obj0 = {}
export { fn0 as foo, obj0 as bar};

//main.js檔案
import {foo, bar} from "./lib";
foo();
console.log(bar);

    

  第三種匯出的方式:

  這種方式是直接在export的地方定義匯出的函式,或者變數:

//lib.js檔案
export let foo = ()=> {console.log("fnFoo") ;return "foo"},bar = "stringBar";

//main.js檔案
import {foo, bar} from "./lib";
console.log(foo());
console.log(bar);

    

  第四種匯出的方式:

  這種匯出的方式不需要知道變數的名字, 相當於是匿名的, 直接把開發的介面給export;
  如果一個js模組檔案就只有一個功能, 那麼就可以使用export default匯出;

//lib.js
export default "string";

//main.js
import defaultString from "./lib";
console.log(defaultString);

    

  第五種匯出方式:

  export也能預設匯出函式, 在import的時候, 名字隨便寫, 因為每一個模組的預設介面就一個:

//lib.js
let fn = () => "string";
export {fn as default};

//main.js
import defaultFn from "./lib";
console.log(defaultFn());

  第六種匯出方式:

  使用萬用字元*  ,重新匯出其他模組的介面 (其實就是轉載文章, 然後不註明出處啦);

//lib.js
export * from "./other";
//如果只想匯出部分介面, 只要把介面名字列出來
//export {foo,fnFoo} from "./other";

//other.js
export let foo = "stringFoo", fnFoo = function() {console.log("fnFoo")};

//main.js
import {foo, fnFoo} from "./lib";
console.log(foo);
console.log(fnFoo());

  

  其他:ES6的import和export提供相當多匯入以及匯出的語法;

  在import的時候可以使用萬用字元*匯入外部的模組:

import * as obj from "./lib";
console.log(obj);

  ES6匯入的模組都是屬於引用:

//lib.js
export let counter = 3;
export function incCounter() {
    counter++;
}
export function setCounter(value) {
    counter = value;
}


//main.js
import { counter, incCounter ,setCounter} from './lib';

// The imported value `counter` is live
console.log(counter); // 3
incCounter();
console.log(counter); // 4
setCounter(0);
console.log(counter); // 0

  在main.js中, counter一直指向lib.js中的區域性變數counter, 按照JS的尿性, 像數字或者字串型別或者布林值的原始值要被複制, 而不是賦址;

  迴圈依賴的問題:


  NodeJS的迴圈依賴是這麼處理的:開啟;

  迴圈依賴是JS模組化帶來的問題, 在瀏覽器端, 使用RequireJS測試模組化, 比如有一個檔案file0.js依賴於file1.js, 而file1.js又依賴於file0.js, 那麼file0.js和file1.js到底誰先執行?

//index.html
<!DOCTYPE html>
<html>
<head>
    <title></title>
    <meta charset="utf-8"/>
</head>
<body>

<script data-main="cyclic" src="//cdn.bootcss.com/require.js/2.2.0/require.min.js"></script>
<script>
//cyclic.js
require(["file0"], function(file0) {
    console.log(file0)
})

//file0.js
define(["file1"], function(file1) {
    console.log(file1)
    return {
        file0 : "file0"
    }
})

//file1.js
define(["file0"], function(file0) {
    console.log(file0);
    return {
        file1 : "file1"
    }
})
</script>
</body>
</html>

  在控制檯的依次輸出為:

undefined
Object { file1: "file1" } 
Object { file0: "file0" }

  在執行file1.js的時候file0.js還沒執行完, 所以輸出了undefined, 這種輸出結果和NodeJS輸出的情況是一樣的;

  然後我又使用了司徒大神的mass-framework框架試了一下, 司徒大神的框架直接提示我: "模組與之前的某些模組存在迴圈依賴", 這樣還比較好點, requireJS對於迴圈依賴是直接執行迴圈依賴的模組, 會導致在開發的時候給自己挖坑....;

  接下來我又在babel-node下進行測試:下面是幾個測試,可以無視:

  我使用ES6的模組試一試, 只要每一個模組被引用, 無論模組是否執行完畢, 該模組的export已經被匯出了, 如果匯出的是函式:

//cyclic.js
import fn0 from "./file0";
fn0();

//file0.js
import fn1 from "./file1";
fn1();
console.log("file0.js runs");
export default function() {console.log("file0 export runs")}

//file1.js
import fn0 from "./file0";
fn0();
console.log("file1.js runs");
export default function() {console.log("file1 export runs")}

  

  如果匯出的是字串:

//cyclic.js
import str from "./file0";
console.log(str);

//file0.js
import str1 from "./file1";
console.log(str1)
console.log("file0.js runs");
export default "str0";

//file1.js
import str0 from "./file0";
console.log(str0)
console.log("file1.js runs");
export default "str1";

  

  如果匯出的是物件:

  那麼第一行會先輸出一個初始值{},在最後等待file0.jsfile1.js執行完畢以後, 才輸出file0.js匯出的物件;

  如果是陣列:

  那麼第一行會輸出一個被靜態分析過的初始值undefined,在最後等待file0.jsfile1.js執行完畢以後, 才輸出file0.js匯出的物件;

  如果是布林值:

  那麼第一行會輸出一個被靜態分析過的初始值undefined,在最後等待file0.jsfile1.js執行完畢以後, 才輸出file0.js匯出的布林值;

  結論:用ES6的export匯出資料介面的時候, 最好統一用函式, 避免在迴圈依賴的時候, 因為JS會把不同型別的物件靜態解析成不同的初始值;

1

1

  瀏覽器相容:

    chrome瀏覽器目前不支援import,和export;

    火狐的支援也有限, 比chrome好;

    我都用babel;

  參考:

相關推薦

ES6特性使用exportimport實現模組

  在ES6前, 前端就使用RequireJS或者seaJS實現模組化, requireJS是基於AMD規範的模組化庫,  而像seaJS是基於CMD規範的模組化庫,  兩者都是為了為了推廣前端模組化的工具, 更多有關AMD和CMD的區別, 後面參考給了幾個連結;    現在ES6自帶了模組化, 也是JS第

JS-exportimport實現模組管理

    JS中經常會用到export和import,以實現程式碼模組化管理。其中:      export:用於對外輸出本模組(一個檔案可以理解為一個模組)變數的介面      im

ES6特性Javascript中的MapWeakMap物件

  Map物件   Map物件是一種有對應 鍵/值 對的物件, JS的Object也是 鍵/值 對的物件 ;   ES6中Map相對於Object物件有幾個區別:   1:Object物件有原型, 也就是說他有預設的key值在物件上面, 除非我們使用Object.create(null)建立一個沒有原型

ES6特性解構賦值(上)

變量賦值 什麽 模式 註意 只需要 一個數 html 代碼 內容 1:什麽是解構賦值 按照一貫的套路,接下來的內容是解釋:什麽是解構賦值? 來看看官方的解釋: ES6允許按照一定模式,從數組和對象中提取值,對變量進行賦值,這被稱為解構(

C++11 標準特性Defaulted Deleted 函式

https://www.ibm.com/developerworks/cn/aix/library/1212_lufang_c11new/index.html 本文將介紹 C++11 標準的兩個新特性:defaulted 和 deleted 函式。對於 default

ES6模塊之exportimport教程

str 童鞋 特性 的人 小明 不知道 這一 strong 概念 一、ES6中的模塊ES6中的模塊即使一個包含JS代碼的文件,在這個模塊中所有的變量都是對其他模塊不可見的,除非我們導出它。ES6的模塊系統大致分為導出(export)和導入(import)兩個模塊。 二、導入

HDFS2.X特性HAFederation聯盟

一、HDFS的新特性HA (一)HDFS的HA機制          Hadoop 2.2.0 版本之前,NameNode是HDFS叢集的單點故障點,每一個叢集只有一個NameNode ,如果這個機器或者程序不可用,整個叢集就

ES6特性解構賦值

ES6 允許按照一定模式,從陣列和物件中提取值,對變數進行賦值,這被稱為解構以前,為變數賦值,只能直接指定值。let x=1;let y=2;let z=3;ES6允許如下寫法let[x,y,z]=[1

HDFS2的特性HAFederation

一、HDFS的新特性HA (一)HDFS的HA機制         Hadoop 2.2.0 版本之前,NameNode是HDFS叢集的單點故障點,每一個叢集只有一個NameNode ,如果這個機器或者程序不可用,整個叢集就無法使用,直到重啟NameNode或者新重啟一

ES6特性Generator以及衍生NPM庫CO入門

2015年ES6的釋出帶來了一系列的JS新特性,Generator在其中屬於一個比較重要的新特性,這裡就詳細地介紹一下。 function* helloWorldGenerator() { yield 'hello'; yield 'world';

筆記ES6特性-變數宣告關鍵字letconst

變數的宣告 ES6在對變數進行宣告時,除了可使用原有的var之外,還可以使用兩個新的關鍵字: 1. let :定義變數 2. const :定義常量 新關鍵字的特點 1. 不可重複定義同名變數,定義同名變數時,會報錯。 2. 使用const定義

【Java並發編程】之二十並發特性—Lock鎖條件變量(含代碼)

ets exc n) 否則 max 長時間 info trace space 簡單使用Lock鎖 Java 5中引入了新的鎖機制——Java.util.concurrent.locks中的顯式的互斥鎖:Lock接口,它提供了比synchronized更加廣泛的鎖

JDK8特性接口的靜態方法默認方法

tool IT highlight RR 類名 another 存在 ltm tar 在jdk8之前,interface之中可以定義變量和方法,變量必須是public、static、final的,方法必須是public、abstract的。由於這些修飾符都是默認的,所以在J

Oracle Database 12c 特性RAC Cluster Hub Node Leaf Node

Oracle Database 12c 新特性:RAC Cluster Hub Node 和 Leaf Node 在 Oracle Database 12c 的 Cluster 中引入了很多新特性和新概念,其中重複最多的幾個名詞除了 Flex Cluster、F

看透Java8特性lambda表示式Stream API

Java11前兩天都發布了,Java8還沒搞清都有啥,這就很尷尬了~ Java8 的新特性:Lambda表示式、強大的 Stream API、全新時間日期 API、ConcurrentHashMap、MetaSpace。Java8 的新特性使 Java 的執行速度更快、程式碼更少(Lambda 表示式)、便

ES6 模組 export import

1.定義模組: export const a = 1 export default b = 2 2.匯入模組 import {a} from './xxxxx' import b from './xxxxx' 3.區分什麼時候import 需要花括號,什麼時候

Java8特性Lambda表示式函式式介面

Java8新特性:速度更快,程式碼更少,stream API,便於並行,最大化減少空指標異常:Optional Lambda表示式 好處: Lambda是一個匿名函式,可以把lambda表示式理解為一

Kubernetes1.6特性POD高階排程-汙點容忍特性/報告節點問題特性

(一)  核心概念Pod是kubernetes中的核心概念,kubernetes對於Pod的管理也就是對Pod生命週期的管理以及對Pod進行排程管理。Kubernetes早期版本使用系統預設排程器來對Pod進行統一排程管理,在1.2版本中增加了多個排程器特性,多個排程器可以並

ES6特性---let const 命令】

具體參考:http://es6.ruanyifeng.com/#README   let 和 const 命令 let 命令 塊級作用域 const 命令 頂層物件的屬性 global 物件 let 命令 基本用法 ES6 新增了l

【Java併發程式設計】之二十併發特性—Lock鎖條件變數(含程式碼)

簡單使用Lock鎖     Java 5中引入了新的鎖機制——java.util.concurrent.locks中的顯式的互斥鎖:Lock介面,它提供了比synchronized更加廣泛的鎖定操作。Lock介面有3個實現它的類:ReentrantLock、Reetrant