ES6學習?Module語法

在ES6之前,模塊加載方案慢逾,最主要的有CommonJS和AMD兩種。前者用于服務器灭红,后者用于瀏覽器侣滩。ES6實現(xiàn)了模塊功能,而且實現(xiàn)的相當簡單变擒,完全可以取代CommonJS和AMD規(guī)范君珠,成為瀏覽器和服務器通用的模塊解決方案。
ES6模塊的設計思想是盡量的靜態(tài)化娇斑,使得編譯時就能確定模塊的依賴關系策添,以及輸入和輸出的變量材部。CommonJS和AMD模塊,都只能在運行時確定這些東西唯竹。比如乐导,CommonJS模塊就是對象,輸入時必須查找對象屬性摩窃。

// CommonJS模塊
let { stat, exists, readFile } = require('fs');
// 等同于
let _fs = require('fs');
let stat = _fs.stat;
let exists = _fs.exists;
let readfile = _fs.readfile;

上面代碼的實質(zhì)是整體加載fs模塊(即加載fs的所有方法)兽叮,生成一個對象(_fs),然后再從這個對象上面讀取3個方法猾愿。這種加載稱為“運行時加載”鹦聪,因為只有運行時才能得到這個對象,導致完全沒辦法在編譯時做“靜態(tài)優(yōu)化”蒂秘。
ES6模塊不是對象泽本,而是通過export命令顯式指定輸出的代碼,再通過import命令輸入姻僧。

// ES6模塊
import { stat, exists, readFile } from 'fs';

上面代碼的實質(zhì)是從fs模塊加載3個方法规丽,其他方法不加載。這種加載稱為“編譯時加載”或者靜態(tài)加載撇贺,即ES6可以在編譯時就完成模塊加載赌莺,效率要比CommonJS模塊的加載方式高。當然松嘶,這也導致了沒法引用ES6模塊本身艘狭,因為它不是對象。
由于ES6模塊是編譯時加載翠订,使得靜態(tài)分析成為可能巢音。有了它,就能進一步拓寬JavaScript 的語法尽超,比如引入宏(macro)和類型檢驗(type system)這些只能靠靜態(tài)分析實現(xiàn)的功能官撼。
除了靜態(tài)加載帶來的各種好處,ES6模塊還有以下好處似谁。

  • 不再需要UMD模塊格式了傲绣,將來服務器和瀏覽器都會支持ES6模塊格式。目前巩踏,通過各種工具庫斜筐,其實已經(jīng)做到了這一點。
  • 將來瀏覽器的新API就能用模塊格式提供蛀缝,不再必須做成全局變量或者navigator對象的屬性顷链。
  • 不再需要對象作為命名空間(比如Math對象),未來這些功能可以通過模塊提供屈梁。

export

模塊功能主要由兩個命令構(gòu)成:exportimport嗤练。export命令用于規(guī)定模塊的對外接口榛了。import命令用于輸入其他模塊提供的功能。
一個模塊就是一個獨立的文件煞抬。該文件內(nèi)部的所有變量外部無法獲取霜大。如果你希望外部能夠讀取模塊內(nèi)部的某個變量,就必須使用export關鍵字輸出該變量革答。

//profile.js
export var firstName='zhang';
export var year=2000;
//另一種寫法
var firstName='zhang';
var year=2000;
export {firstName,year};

上面代碼在export命令后面战坤,使用大括號指定所要輸出的一組變量。
export命令除了可以輸出變量残拐,還可以輸出函數(shù)或類途茫。

export function multiply(x,y) {
  return x * y;
};

通常情況下,export輸出的變量就是本來的名字溪食,但是可以使用as關鍵字重命名囊卜。

function v1() { ... }
function v2() { ... }

export {
  v1 as streamV1,
  v2 as streamV2,
  v2 as streamLatestVersion
};

重命名后,v2可以用不同的名字輸出兩次错沃。
需要特別注意的是栅组,export命令規(guī)定的是對外的接口,必須與模塊內(nèi)部的變量建立一一對應關系枢析。

// 報錯
export 1;
// 報錯
var m = 1;
export m;

上面兩種寫法都會報錯玉掸,因為沒有提供對外的接口。第一種寫法直接輸出1醒叁,第二種寫法通過變量m司浪,還是直接輸出1。1只是一個值辐益,不是接口。正確的寫法是下面這樣脱吱。

// 寫法一
export var m = 1;
// 寫法二
var m = 1;
export {m};
// 寫法三
var n = 1;
export {n as m};

上面三種寫法都是正確的智政,規(guī)定了對外的接口m。其他腳本可以通過這個接口箱蝠,取到值1续捂。它們的實質(zhì)是,在接口名與模塊內(nèi)部變量之間宦搬,建立了一一對應的關系牙瓢。
同樣的,functionclass的輸出间校,也必須遵守這樣的寫法矾克。

// 報錯
function f() {}
export f;
// 正確
export function f() {};
// 正確
function f() {}
export {f};

另外,export語句輸出的接口憔足,與其對應的值是動態(tài)綁定關系胁附,即通過該接口酒繁,可以取到模塊內(nèi)部實時的值。這一點與CommonJS規(guī)范完全不同控妻。CommonJS模塊輸出的是值的緩存州袒,不存在動態(tài)更新。

export var foo = 'bar';
setTimeout(() => foo = 'baz', 500);

最后弓候,export命令可以出現(xiàn)在模塊的任何位置郎哭,只要處于模塊頂層就可以。如果處于塊級作用域內(nèi)菇存,就會報錯夸研,import命令也是如此。這是因為處于條件代碼塊之中撰筷,就沒法做靜態(tài)優(yōu)化了陈惰,違背了ES6 模塊的設計初衷。

function foo() {
  export default 'bar' // SyntaxError
}
foo()

import

使用export命令定義了模塊的對外接口以后毕籽,其他JS文件就可以通過import命令加載這個模塊抬闯。

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

import命令接受一對大括號,里面指定要從其他模塊導入的變量名关筒。大括號里面的變量名溶握,必須與被導入模塊對外接口的名稱相同。
如果想為輸入的變量重新取一個名字蒸播,import命令要使用as關鍵字睡榆,將輸入的變量重命名。

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

import命令輸入的變量都是只讀的袍榆,因為它的本質(zhì)是輸入接口胀屿。也就是說,不允許在加載模塊的腳本里面包雀,改寫接口宿崭。

import {a} from './xxx.js'
a = {}; // Syntax Error : 'a' is read-only;

上面代碼中,腳本加載了變量a才写,對其重新賦值就會報錯葡兑,因為a是一個只讀的接口。但是赞草,如果a是一個對象讹堤,改寫a的屬性是允許的。

import {a} from './xxx.js'
a.foo = 'hello'; // 合法操作

import后面的from指定模塊文件的位置厨疙,可以是相對路徑洲守,也可以是絕對路徑,.js后綴可以省略。如果只是模塊名岖沛,不帶有路徑暑始,那么必須有配置文件,告訴JS引擎該模塊的位置婴削。

import {myMethod} from 'util';

注意廊镜,import命令具有提升效果,會提升到整個模塊的頭部唉俗,首先執(zhí)行嗤朴。

foo();
import { foo } from 'my_module';

上面的代碼不會報錯,因為import的執(zhí)行早于foo的調(diào)用虫溜。這種行為的本質(zhì)是雹姊,import命令是編譯階段執(zhí)行的,在代碼運行之前衡楞。
由于import是靜態(tài)執(zhí)行吱雏,所以不能使用表達式和變量,這些只有在運行時才能得到結(jié)果的語法結(jié)構(gòu)瘾境。

// 報錯
import { 'f' + 'oo' } from 'my_module';
// 報錯
let module = 'my_module';
import { foo } from module;
// 報錯
if (x === 1) {
  import { foo } from 'module1';
} else {
  import { foo } from 'module2';
}

最后歧杏,import語句會執(zhí)行所加載的模塊,因此可以有下面的寫法迷守。

import 'lodash';

上面代碼僅僅執(zhí)行lodash模塊犬绒,但是不輸入任何值。
如果多次重復執(zhí)行同一句import語句兑凿,那么只會執(zhí)行一次凯力,而不會執(zhí)行多次。

import 'lodash';
import 'lodash';

import { foo } from 'my_module';
import { bar } from 'my_module';
// 等同于
import { foo, bar } from 'my_module';

目前階段礼华,通過Babel轉(zhuǎn)碼咐鹤,CommonJS模塊的require命令和ES6模塊的import命令,可以寫在同一個模塊里面圣絮,但是最好不要這樣做祈惶。因為import在靜態(tài)解析階段執(zhí)行,所以它是一個模塊之中最早執(zhí)行的晨雳。

模塊的整體加載

除了指定加載某個輸出值行瑞,還可以使用整體加載奸腺,即用星號(*)指定一個對象餐禁,所有輸出值都加載在這個對象上面。

// circle.js
export function area(radius) {
  return Math.PI * radius * radius;
}
export function circumference(radius) {
  return 2 * Math.PI * radius;
}

現(xiàn)在捷绒,加載這個模塊斑粱。

// main.js
import { area, circumference } from './circle';
console.log('圓面積:'+area(4));
console.log('圓周長:'+circumference(14));

上面寫法是逐一指定要加載的方法刮便,整體加載的寫法如下怀樟。

import * as circle from './circle';
console.log('圓面積:' + circle.area(4));
console.log('圓周長:' + circle.circumference(14));

注意末盔,模塊整體加載所在的那個對象(上例是circle)筑舅,應該是可以靜態(tài)分析的,所以不允許運行時改變陨舱。下面的寫法都是不允許的翠拣。

import * as circle from './circle';
// 下面兩行都是不允許的
circle.foo = 'hello';
circle.area = function () {};

export default命令

使用import命令的時候,用戶需要知道所要加載的變量名或函數(shù)名游盲,否則無法加載误墓。為了給用戶提供方便,就要用到export default命令益缎,為模塊指定默認輸出谜慌。

// export-default.js
export default function () {
  console.log('foo');
}

上面代碼是一個模塊文件export-default.js,它的默認輸出是一個函數(shù)莺奔。
其他模塊加載該模塊時欣范,import命令可以為該匿名函數(shù)指定任意名字。

// import-default.js
import customName from './export-default';
customName(); // 'foo'

上面代碼的import命令令哟,可以用任意名稱指向export-default.js輸出的方法恼琼,這時就不需要知道原模塊輸出的函數(shù)名。需要注意的是励饵,這時import命令后面驳癌,不使用大括號。
export default命令用在非匿名函數(shù)前役听,也是可以的颓鲜。

// export-default.js
export default function foo() {
  console.log('foo');
}
// 或者寫成
function foo() {
  console.log('foo');
}
export default foo;

上面代碼中,foo函數(shù)的函數(shù)名foo典予,在模塊外部是無效的甜滨。加載的時候,視同匿名函數(shù)加載瘤袖。
下面比較一下默認輸出和正常輸出衣摩。

// 第一組
export default function crc32() { // 輸出
  // ...
}
import crc32 from 'crc32'; // 輸入
// 第二組
export function crc32() { // 輸出
  // ...
};
import {crc32} from 'crc32'; // 輸入

上面代碼的兩組寫法,第一組是使用export default時捂敌,對應的import語句不需要使用大括號艾扮;第二組是不使用export default時,對應的import語句需要使用大括號占婉。
export default命令用于指定模塊的默認輸出泡嘴。顯然,一個模塊只能有一個默認輸出逆济,因此export default命令只能使用一次酌予。所以磺箕,import命令后面才不用加大括號,因為只可能唯一對應export default命令抛虫。
本質(zhì)上松靡,export default就是輸出一個叫做default的變量或方法,然后系統(tǒng)允許你為它取任意名字建椰。所以雕欺,下面的寫法是有效的。

// modules.js
function add(x, y) {
  return x * y;
}
export {add as default};
// 等同于
// export default add;

// app.js
import { default as foo } from 'modules';
// 等同于
// import foo from 'modules';

正是因為export default命令其實只是輸出一個叫做default的變量棉姐,所以它后面不能跟變量聲明語句阅茶。

// 正確
export var a = 1;
// 正確
var a = 1;
export default a;
// 錯誤
export default var a = 1;

上面代碼中,export default a的含義是將變量a的值賦給變量default谅海。所以脸哀,最后一種寫法會報錯。
同樣地扭吁,因為export default命令的本質(zhì)是將后面的值撞蜂,賦給default變量,所以可以直接將一個值寫在export default之后侥袜。

// 正確
export default 42;
// 報錯
export 42;

有了export default命令蝌诡,輸入模塊時就非常直觀了,以輸入lodash模塊為例枫吧。

import _ from 'lodash';

如果想在一條import語句中浦旱,同時輸入默認方法和其他接口,可以寫成下面這樣九杂。

import _,{each,each as forEach} from 'lodash';

對應上面代碼的export語句如下颁湖。

export default function (obj) {
  // ···
}
export function each(obj, iterator, context) {
  // ···
}
export { each as forEach };

export default也可以用來輸出類。

// MyClass.js
export default class { ... }
// main.js
import MyClass from 'MyClass';
let o = new MyClass();

export與import的復合寫法

如果在一個模塊之中例隆,先輸入后輸出同一個模塊甥捺,import語句可以與export語句寫在一起。

export { foo, bar } from 'my_module';
// 可以簡單理解為
import { foo, bar } from 'my_module';
export { foo, bar };

上面代碼中镀层,exportimport語句可以結(jié)合在一起镰禾,寫成一行。但需要注意的是唱逢,寫成一行以后吴侦,foobar實際上并沒有被導入當前模塊,只是相當于對外轉(zhuǎn)發(fā)了這兩個接口坞古,導致當前模塊不能直接使用foobar备韧。
模塊的接口改名和整體輸出,也可以采用這種寫法绸贡。

// 接口改名
export { foo as myFoo } from 'my_module';
// 整體輸出
export * from 'my_module';
默認接口的寫法如下盯蝴。
export { default } from 'foo';

具名接口改為默認接口的寫法如下。

export { es6 as default } from './someModule';
// 等同于
import { es6 } from './someModule';
export default es6;

同樣地听怕,默認接口也可以改名為具名接口捧挺。

export { default as es6 } from './someModule';

下面三種import語句,沒有對應的復合寫法尿瞭。

import * as someIdentifier from "someModule";
import someIdentifier from "someModule";
import someIdentifier, { namedIdentifier } from "someModule";

為了做到形式的對稱闽烙,現(xiàn)在有提案,提出補上這三種復合寫法声搁。

export * as someIdentifier from "someModule";
export someIdentifier from "someModule";
export someIdentifier, { namedIdentifier } from "someModule";

模塊的繼承

模塊之間也可以繼承黑竞。
假設有一個circleplus模塊,繼承了circle模塊疏旨。

// circleplus.js
export * from 'circle';
export var e = 2.71828182846;
export default function(x) {
  return Math.exp(x);
}

上面代碼中的export *很魂,表示再輸出circle模塊的所有屬性和方法。注意檐涝,export *命令會忽略circle模塊的default方法遏匆。然后,上面代碼又輸出了自定義的e變量和默認方法谁榜。
這時幅聘,也可以將circle的屬性或方法,改名后再輸出窃植。

// circleplus.js
export { area as circleArea } from 'circle';

上面代碼表示帝蒿,只輸出circle模塊的area方法,且將其改名為circleArea巷怜。
加載上面模塊的寫法如下葛超。

// main.js
import * as math from 'circleplus';
import exp from 'circleplus';
console.log(exp(math.e));

上面代碼中的import exp表示,將circleplus模塊的默認方法加載為exp方法延塑。

跨模塊常量

const聲明的常量只在當前代碼塊有效巩掺。如果想設置跨模塊的常量(即跨多個文件),或者說一個值要被多個模塊共享页畦,可以采用下面的寫法胖替。

// constants.js 模塊
export const A = 1;
export const B = 3;
export const C = 4;
// test1.js 模塊
import * as constants from './constants';
console.log(constants.A); // 1
console.log(constants.B); // 3
// test2.js 模塊
import {A, B} from './constants';
console.log(A); // 1
console.log(B); // 3

如果要使用的常量非常多,可以建一個專門的constants目錄豫缨,將各種常量寫在不同的文件里面独令,保存在該目錄下。

// constants/db.js
export const db = {
  url: 'http://my.couchdbserver.local:5984',
  admin_username: 'admin',
  admin_password: 'admin password'
};
// constants/user.js
export const users = ['root', 'admin', 'staff', 'ceo', 'chief', 'moderator'];

然后好芭,將這些文件輸出的常量燃箭,合并在index.js里面。

// constants/index.js
export {db} from './db';
export {users} from './users';

使用的時候舍败,直接加載index.js就可以了招狸。

// script.js
import {db, users} from './index';

import()

import命令會被JS引擎靜態(tài)分析敬拓,先于模塊內(nèi)的其他語句執(zhí)行。所以裙戏,下面的代碼會報錯乘凸。

// 報錯
if (x === 2) {
  import MyModual from './myModual';
}

上面代碼中,引擎處理import語句是在編譯時累榜,這時不會去分析或執(zhí)行if語句营勤,所以import語句放在if代碼塊之中毫無意義,因此會報句法錯誤壹罚,而不是執(zhí)行時錯誤葛作。也就是說,importexport命令只能在模塊的頂層猖凛,不能在代碼塊之中赂蠢。
這樣的設計,固然有利于編譯器提高效率辨泳,但也導致無法在運行時加載模塊客年。在語法上,條件加載就不可能實現(xiàn)漠吻。如果import命令要取代Node的require方法量瓜,這就形成了一個障礙。因為require是運行時加載模塊途乃,import命令無法取代require的動態(tài)加載功能绍傲。

const path = './' + fileName;
const myModual = require(path);

上面的語句就是動態(tài)加載,require到底加載哪一個模塊耍共,只有運行時才知道烫饼。import命令做不到這一點。
因此试读,有一個提案杠纵,建議引入import()函數(shù),完成動態(tài)加載钩骇。

import(specifier)

上面代碼中比藻,import函數(shù)的參數(shù)specifier,指定所要加載的模塊的位置倘屹。import命令能夠接受什么參數(shù)银亲,import()函數(shù)就能接受什么參數(shù),兩者區(qū)別主要是后者為動態(tài)加載纽匙。
import()返回一個Promise對象务蝠。下面是一個例子。

const main = document.querySelector('main');
import(`./section-modules/${someVariable}.js`)
  .then(module => {
    module.loadPageInto(main);
  })
  .catch(err => {
    main.textContent = err.message;
  });

import()函數(shù)可以用在任何地方烛缔,不僅僅是模塊馏段,非模塊的腳本也可以使用轩拨。它是運行時執(zhí)行,也就是說院喜,什么時候運行到這一句亡蓉,就會加載指定的模塊。另外够坐,import()函數(shù)與所加載的模塊沒有靜態(tài)連接關系,這點也是與import語句不相同崖面。import()類似于 Node 的require方法元咙,區(qū)別主要是前者是異步加載,后者是同步加載巫员。

適用場合

下面是import()的一些適用場合庶香。

1.按需加載。

import()可以在需要的時候简识,再加載某個模塊赶掖。

button.addEventListener('click', event => {
  import('./dialogBox.js')
  .then(dialogBox => {
    dialogBox.open();
  })
  .catch(error => {
    /* Error handling */
  })
});

上面代碼中,import()方法放在click事件的監(jiān)聽函數(shù)之中七扰,只有用戶點擊了按鈕奢赂,才會加載這個模塊。

2.條件加載

import()可以放在if代碼塊颈走,根據(jù)不同的情況膳灶,加載不同的模塊。

if (condition) {
  import('moduleA').then(...);
} else {
  import('moduleB').then(...);
}
3.動態(tài)的模塊路徑

import()允許模塊路徑動態(tài)生成立由。

import(f()).then(...);

上面代碼中轧钓,根據(jù)函數(shù)f的返回結(jié)果,加載不同的模塊锐膜。

注意點

import()加載模塊成功以后毕箍,這個模塊會作為一個對象,當作then方法的參數(shù)道盏。因此而柑,可以使用對象解構(gòu)賦值的語法,獲取輸出接口荷逞。

import('./myModule.js')
.then(({export1, export2}) => {
  // ...·
});

上面代碼中牺堰,export1export2都是myModule.js的輸出接口,可以解構(gòu)獲得颅围。
如果模塊有default輸出接口伟葫,可以用參數(shù)直接獲得。

import('./myModule.js')
.then(myModule => {
  console.log(myModule.default);
});

上面的代碼也可以使用具名輸入的形式院促。

import('./myModule.js')
.then(({default: theDefault}) => {
  console.log(theDefault);
});

如果想同時加載多個模塊筏养,可以采用下面的寫法斧抱。

Promise.all([
  import('./module1.js'),
  import('./module2.js'),
  import('./module3.js'),
])
.then(([module1, module2, module3]) => {
   ···
});

import()也可以用在async函數(shù)之中。

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();
最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末渐溶,一起剝皮案震驚了整個濱河市辉浦,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌茎辐,老刑警劉巖宪郊,帶你破解...
    沈念sama閱讀 222,252評論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異拖陆,居然都是意外死亡弛槐,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,886評論 3 399
  • 文/潘曉璐 我一進店門依啰,熙熙樓的掌柜王于貴愁眉苦臉地迎上來乎串,“玉大人,你說我怎么就攤上這事速警√居” “怎么了?”我有些...
    開封第一講書人閱讀 168,814評論 0 361
  • 文/不壞的土叔 我叫張陵闷旧,是天一觀的道長长豁。 經(jīng)常有香客問我,道長忙灼,這世上最難降的妖魔是什么蕉斜? 我笑而不...
    開封第一講書人閱讀 59,869評論 1 299
  • 正文 為了忘掉前任,我火速辦了婚禮缀棍,結(jié)果婚禮上宅此,老公的妹妹穿的比我還像新娘。我一直安慰自己爬范,他們只是感情好父腕,可當我...
    茶點故事閱讀 68,888評論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著青瀑,像睡著了一般璧亮。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上斥难,一...
    開封第一講書人閱讀 52,475評論 1 312
  • 那天枝嘶,我揣著相機與錄音,去河邊找鬼哑诊。 笑死群扶,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播竞阐,決...
    沈念sama閱讀 41,010評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼缴饭,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了骆莹?” 一聲冷哼從身側(cè)響起颗搂,我...
    開封第一講書人閱讀 39,924評論 0 277
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎幕垦,沒想到半個月后丢氢,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,469評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡先改,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,552評論 3 342
  • 正文 我和宋清朗相戀三年疚察,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片盏道。...
    茶點故事閱讀 40,680評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡稍浆,死狀恐怖载碌,靈堂內(nèi)的尸體忽然破棺而出猜嘱,到底是詐尸還是另有隱情,我是刑警寧澤嫁艇,帶...
    沈念sama閱讀 36,362評論 5 351
  • 正文 年R本政府宣布朗伶,位于F島的核電站,受9級特大地震影響步咪,放射性物質(zhì)發(fā)生泄漏论皆。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 42,037評論 3 335
  • 文/蒙蒙 一猾漫、第九天 我趴在偏房一處隱蔽的房頂上張望点晴。 院中可真熱鬧,春花似錦悯周、人聲如沸粒督。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,519評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽屠橄。三九已至,卻和暖如春闰挡,著一層夾襖步出監(jiān)牢的瞬間锐墙,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,621評論 1 274
  • 我被黑心中介騙來泰國打工长酗, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留溪北,地道東北人。 一個月前我還...
    沈念sama閱讀 49,099評論 3 378
  • 正文 我出身青樓,卻偏偏與公主長得像刻盐,于是被迫代替她去往敵國和親掏膏。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,691評論 2 361

推薦閱讀更多精彩內(nèi)容

  • 概述 歷史上敦锌,JavaScript 一直沒有模塊(module)體系馒疹,無法將一個大程序拆分成互相依賴的小文件,再用...
    emmet7life閱讀 618評論 0 0
  • ES6模塊不是對象乙墙,而是export命令顯示指定輸出的代碼颖变,輸入時也采用靜態(tài)命令的形式。 上面是從fs模塊里加載3...
    竹天亮閱讀 7,554評論 2 17
  • 模塊通常是指編程語言所提供的代碼組織機制听想,利用此機制可將程序拆解為獨立且通用的代碼單元腥刹。所謂模塊化主要是解決代碼分...
    MapleLeafFall閱讀 1,171評論 0 0
  • 上一篇文章為:→5.1.3表示字符 原始字符串 說明 Python中字符串前面加上 r 表示原生字符串衔峰, 與大多數(shù)...
    lyh165閱讀 285評論 0 1
  • 遍覽群書, 只為尋覓一幅心儀的畫卷蛙粘。 循著畫里的樣子垫卤, 建幾棟茅屋,種幾株曼達出牧。 從此住下穴肘, 唱詩,寫曲舔痕, 回憶一...
    朝云無覓處閱讀 277評論 0 1