摘要:所有依賴這個(gè)模塊的語(yǔ)句,都定義在一個(gè)回調(diào)函數(shù)中,等到加載完成之后,這個(gè)回調(diào)函數(shù)才會(huì)運(yùn)行。目前,主要有兩個(gè)庫(kù)實(shí)現(xiàn)了規(guī)范和。這些導(dǎo)出對(duì)象用名稱進(jìn)行區(qū)分,稱之為命名式導(dǎo)出。
簡(jiǎn)單粗暴,富婆給你說(shuō),其實(shí)我也沒(méi)太搞明白,最近看了一篇文章我才理清了一點(diǎn)點(diǎn)思路,最近整日沉迷于肥宅快樂(lè)水,技術(shù)都跟不上了,來(lái)篇文章,提神醒腦,朝著我的富婆夢(mèng)更近一步,早日走上富婆路,包養(yǎng)我家大狼狗!!!
為什么有模塊概念理想情況下,開(kāi)發(fā)者只需要實(shí)現(xiàn)核心的業(yè)務(wù)邏輯,其他都可以加載別人已經(jīng)寫(xiě)好的模塊。
但是,Javascript不是一種模塊化編程語(yǔ)言,在es6以前,它是不支持”類”(class),所以也就沒(méi)有”模塊”(module)了。
Javascript社區(qū)做了很多努力,在現(xiàn)有的運(yùn)行環(huán)境中,實(shí)現(xiàn)”模塊”的效果。
原始寫(xiě)法模塊就是實(shí)現(xiàn)特定功能的一組方法。
只要把不同的函數(shù)(以及記錄狀態(tài)的變量)簡(jiǎn)單地放在一起,就算是一個(gè)模塊。
function m1(){ //... } function m2(){ //... }
上面的函數(shù)m1()和m2(),組成一個(gè)模塊。使用的時(shí)候,直接調(diào)用就行了。
這種做法的缺點(diǎn)很明顯:”污染”了全局變量,無(wú)法保證不與其他模塊發(fā)生變量名沖突,而且模塊成員之間看不出直接關(guān)系。
對(duì)象寫(xiě)法
為了解決上面的缺點(diǎn),可以把模塊寫(xiě)成一個(gè)對(duì)象,所有的模塊成員都放到這個(gè)對(duì)象里面
var module1 = new Object({ _count : 0, m1 : function (){ //... }, m2 : function (){ //... } });
上面的函數(shù)m1()和m2(),都封裝在module1對(duì)象里。使用的時(shí)候,就是調(diào)用這個(gè)對(duì)象的屬性
module1.m1();
這樣的寫(xiě)法會(huì)暴露所有模塊成員,內(nèi)部狀態(tài)可以被外部改寫(xiě)。比如,外部代碼可以直接改變內(nèi)部計(jì)數(shù)器的值。
module._count = 1;
立即執(zhí)行函數(shù)寫(xiě)法
使用”立即執(zhí)行函數(shù)”(Immediately-Invoked Function Expression,IIFE),可以達(dá)到不暴露私有成員的目的
var module = (function() { var _count = 0; var m1 = function() { alert(_count) } var m2 = function() { alert(_count + 1) } return { m1: m1, m2: m2 } })()
使用上面的寫(xiě)法,外部代碼無(wú)法讀取內(nèi)部的_count變量。
console.info(module._count); //undefined
module就是Javascript模塊的基本寫(xiě)法。
主流模塊規(guī)范在es6以前,還沒(méi)有提出一套官方的規(guī)范,從社區(qū)和框架推廣程度而言,目前通行的javascript模塊規(guī)范有兩種:CommonJS 和 AMD
CommonJS規(guī)范2009年,美國(guó)程序員Ryan Dahl創(chuàng)造了node.js項(xiàng)目,將javascript語(yǔ)言用于服務(wù)器端編程。
這標(biāo)志”Javascript模塊化編程”正式誕生。前端的復(fù)雜程度有限,沒(méi)有模塊也是可以的,但是在服務(wù)器端,一定要有模塊,與操作系統(tǒng)和其他應(yīng)用程序互動(dòng),否則根本沒(méi)法編程。
node編程中最重要的思想之一就是模塊,而正是這個(gè)思想,讓JavaScript的大規(guī)模工程成為可能。模塊化編程在js界流行,也是基于此,隨后在瀏覽器端,requirejs和seajs之類的工具包也出現(xiàn)了,可以說(shuō)在對(duì)應(yīng)規(guī)范下,require統(tǒng)治了ES6之前的所有模塊化編程,即使現(xiàn)在,在ES6 module被完全實(shí)現(xiàn)之前,還是這樣。
在CommonJS中,暴露模塊使用module.exports和exports,很多人不明白暴露對(duì)象為什么會(huì)有兩個(gè),后面會(huì)介紹區(qū)別
在CommonJS中,有一個(gè)全局性方法require(),用于加載模塊。假定有一個(gè)數(shù)學(xué)模塊math.js,就可以像下面這樣加載。
var math = require("math");
然后,就可以調(diào)用模塊提供的方法:
var math = require("math"); math.add(2,3); // 5
正是由于CommonJS 使用的require方式的推動(dòng),才有了后面的AMD、CMD 也采用的require方式來(lái)引用模塊的風(fēng)格
AMD規(guī)范有了服務(wù)器端模塊以后,很自然地,大家就想要客戶端模塊。而且最好兩者能夠兼容,一個(gè)模塊不用修改,在服務(wù)器和瀏覽器都可以運(yùn)行。
但是,由于一個(gè)重大的局限,使得CommonJS規(guī)范不適用于瀏覽器環(huán)境。還是上一節(jié)的代碼,如果在瀏覽器中運(yùn)行,會(huì)有一個(gè)很大的問(wèn)題
var math = require("math"); math.add(2, 3);
第二行math.add(2, 3),在第一行require(‘math’)之后運(yùn)行,因此必須等math.js加載完成。也就是說(shuō),如果加載時(shí)間很長(zhǎng),整個(gè)應(yīng)用就會(huì)停在那里等。
這對(duì)服務(wù)器端不是一個(gè)問(wèn)題,因?yàn)樗械哪K都存放在本地硬盤(pán),可以同步加載完成,等待時(shí)間就是硬盤(pán)的讀取時(shí)間。但是,對(duì)于瀏覽器,這卻是一個(gè)大問(wèn)題,因?yàn)槟K都放在服務(wù)器端,等待時(shí)間取決于網(wǎng)速的快慢,可能要等很長(zhǎng)時(shí)間,瀏覽器處于”假死”狀態(tài)。
因此,瀏覽器端的模塊,不能采用”同步加載”(synchronous),只能采用”異步加載”(asynchronous)。這就是AMD規(guī)范誕生的背景。
AMD是”Asynchronous Module Definition”的縮寫(xiě),意思就是”異步模塊定義”。它采用異步方式加載模塊,模塊的加載不影響它后面語(yǔ)句的運(yùn)行。所有依賴這個(gè)模塊的語(yǔ)句,都定義在一個(gè)回調(diào)函數(shù)中,等到加載完成之后,這個(gè)回調(diào)函數(shù)才會(huì)運(yùn)行。
模塊必須采用特定的define()函數(shù)來(lái)定義。
define(id?, dependencies?, factory)
id:字符串,模塊名稱(可選)
dependencies: 是我們要載入的依賴模塊(可選),使用相對(duì)路徑。,注意是數(shù)組格式
factory: 工廠方法,返回一個(gè)模塊函數(shù)
如果一個(gè)模塊不依賴其他模塊,那么可以直接定義在define()函數(shù)之中。
// math.js define(function (){ var add = function (x,y){ return x+y; }; return { add: add }; });
如果這個(gè)模塊還依賴其他模塊,那么define()函數(shù)的第一個(gè)參數(shù),必須是一個(gè)數(shù)組,指明該模塊的依賴性。
define(["Lib"], function(Lib){ function foo(){ Lib.doSomething(); } return { foo : foo }; });
當(dāng)require()函數(shù)加載上面這個(gè)模塊的時(shí)候,就會(huì)先加載Lib.js文件。
AMD也采用require()語(yǔ)句加載模塊,但是不同于CommonJS,它要求兩個(gè)參數(shù):
require([module], callback);
第一個(gè)參數(shù)[module],是一個(gè)數(shù)組,里面的成員就是要加載的模塊;第二個(gè)參數(shù)callback,則是加載成功之后的回調(diào)函數(shù)。如果將前面的代碼改寫(xiě)成AMD形式,就是下面這樣:
require(["math"], function (math) { math.add(2, 3); });
math.add()與math模塊加載不是同步的,瀏覽器不會(huì)發(fā)生假死。所以很顯然,AMD比較適合瀏覽器環(huán)境。
目前,主要有兩個(gè)Javascript庫(kù)實(shí)現(xiàn)了AMD規(guī)范:require.js和curl.js。
CMD規(guī)范CMD (Common Module Definition), 是seajs推崇的規(guī)范,CMD則是依賴就近,用的時(shí)候再require。它寫(xiě)起來(lái)是這樣的:
define(function(require, exports, module) { var clock = require("clock"); clock.start(); });
CMD與AMD一樣,也是采用特定的define()函數(shù)來(lái)定義,用require方式來(lái)引用模塊
define(id?, dependencies?, factory)
id:字符串,模塊名稱(可選)
dependencies: 是我們要載入的依賴模塊(可選),使用相對(duì)路徑。,注意是數(shù)組格式
factory: 工廠方法,返回一個(gè)模塊函數(shù)
define("hello", ["jquery"], function(require, exports, module) { // 模塊代碼 });
如果一個(gè)模塊不依賴其他模塊,那么可以直接定義在define()函數(shù)之中。
define(function(require, exports, module) { // 模塊代碼 });
注意:帶 id 和 dependencies 參數(shù)的 define 用法不屬于 CMD 規(guī)范,而屬于 Modules/Transport 規(guī)范。
CMD與AMD區(qū)別AMD和CMD最大的區(qū)別是對(duì)依賴模塊的執(zhí)行時(shí)機(jī)處理不同,而不是加載的時(shí)機(jī)或者方式不同,二者皆為異步加載模塊。
AMD依賴前置,js可以方便知道依賴模塊是誰(shuí),立即加載;
而CMD就近依賴,需要使用把模塊變?yōu)樽址馕鲆槐椴胖酪蕾嚵四切┠K,這也是很多人詬病CMD的一點(diǎn),犧牲性能來(lái)帶來(lái)開(kāi)發(fā)的便利性,實(shí)際上解析模塊用的時(shí)間短到可以忽略。
現(xiàn)階段的標(biāo)準(zhǔn)
ES6標(biāo)準(zhǔn)發(fā)布后,module成為標(biāo)準(zhǔn),標(biāo)準(zhǔn)使用是以export指令導(dǎo)出接口,以import引入模塊,但是在我們一貫的node模塊中,我們依然采用的是CommonJS規(guī)范,使用require引入模塊,使用module.exports導(dǎo)出接口。
export導(dǎo)出模塊
export語(yǔ)法聲明用于導(dǎo)出函數(shù)、對(duì)象、指定文件(或模塊)的原始值。
注意:在node中使用的是exports,不要混淆了.
export有兩種模塊導(dǎo)出方式:命名式導(dǎo)出(名稱導(dǎo)出)和默認(rèn)導(dǎo)出(定義式導(dǎo)出),命名式導(dǎo)出每個(gè)模塊可以多個(gè),而默認(rèn)導(dǎo)出每個(gè)模塊僅一個(gè)。
export { name1, name2, …, nameN }; export { variable1 as name1, variable2 as name2, …, nameN }; export let name1, name2, …, nameN; // also var export let name1 = …, name2 = …, …, nameN; // also var, const export default expression; export default function (…) { … } // also class, function* export default function name1(…) { … } // also class, function* export { name1 as default, … }; export * from …; export { name1, name2, …, nameN } from …; export { import1 as name1, import2 as name2, …, nameN } from …;
name1… nameN-導(dǎo)出的“標(biāo)識(shí)符”。導(dǎo)出后,可以通過(guò)這個(gè)“標(biāo)識(shí)符”在另一個(gè)模塊中使用import引用
default-設(shè)置模塊的默認(rèn)導(dǎo)出。設(shè)置后import不通過(guò)“標(biāo)識(shí)符”而直接引用默認(rèn)導(dǎo)入
-繼承模塊并導(dǎo)出繼承模塊所有的方法和屬性
as-重命名導(dǎo)出“標(biāo)識(shí)符”
from-從已經(jīng)存在的模塊、腳本文件…導(dǎo)出
命名式導(dǎo)出
模塊可以通過(guò)export前綴關(guān)鍵詞聲明導(dǎo)出對(duì)象,導(dǎo)出對(duì)象可以是多個(gè)。這些導(dǎo)出對(duì)象用名稱進(jìn)行區(qū)分,稱之為命名式導(dǎo)出。
export { myFunction }; // 導(dǎo)出一個(gè)已定義的函數(shù) export const foo = Math.sqrt(2); // 導(dǎo)出一個(gè)常量
我們可以使用*和from關(guān)鍵字來(lái)實(shí)現(xiàn)的模塊的繼承:
export * from "article";
模塊導(dǎo)出時(shí),可以指定模塊的導(dǎo)出成員。導(dǎo)出成員可以認(rèn)為是類中的公有對(duì)象,而非導(dǎo)出成員可以認(rèn)為是類中的私有對(duì)象:
var name = "IT筆錄"; var domain = "http://itbilu.com"; export {name, domain}; // 相當(dāng)于導(dǎo)出 {name:name,domain:domain}
模塊導(dǎo)出時(shí),我們可以使用as關(guān)鍵字對(duì)導(dǎo)出成員進(jìn)行重命名:
var name = "IT筆錄"; var domain = "http://itbilu.com"; export {name as siteName, domain};
注意,下面的語(yǔ)法有嚴(yán)重錯(cuò)誤的情況:
// 錯(cuò)誤演示 export 1; // 絕對(duì)不可以 var a = 100; export a;
export在導(dǎo)出接口的時(shí)候,必須與模塊內(nèi)部的變量具有一一對(duì)應(yīng)的關(guān)系。直接導(dǎo)出1沒(méi)有任何意義,也不可能在import的時(shí)候有一個(gè)變量與之對(duì)應(yīng)
export a雖然看上去成立,但是a的值是一個(gè)數(shù)字,根本無(wú)法完成解構(gòu),因此必須寫(xiě)成export {a}的形式。即使a被賦值為一個(gè)function,也是不允許的。而且,大部分風(fēng)格都建議,模塊中最好在末尾用一個(gè)export導(dǎo)出所有的接口,例如:
export {fun as default,a,b,c};
默認(rèn)導(dǎo)出
默認(rèn)導(dǎo)出也被稱做定義式導(dǎo)出。命名式導(dǎo)出可以導(dǎo)出多個(gè)值,但在在import引用時(shí),也要使用相同的名稱來(lái)引用相應(yīng)的值。而默認(rèn)導(dǎo)出每個(gè)導(dǎo)出只有一個(gè)單一值,這個(gè)輸出可以是一個(gè)函數(shù)、類或其它類型的值,這樣在模塊import導(dǎo)入時(shí)也會(huì)很容易引用。
export default function() {}; // 可以導(dǎo)出一個(gè)函數(shù) export default class(){}; // 也可以出一個(gè)類
命名式導(dǎo)出與默認(rèn)導(dǎo)出
默認(rèn)導(dǎo)出可以理解為另一種形式的命名導(dǎo)出,默認(rèn)導(dǎo)出可以認(rèn)為是使用了default名稱的命名導(dǎo)出。
下面兩種導(dǎo)出方式是等價(jià)的:
const D = 123; export default D; export { D as default };
export使用示例
使用名稱導(dǎo)出一個(gè)模塊時(shí):
// "my-module.js" 模塊 export function cube(x) { return x * x * x; } const foo = Math.PI + Math.SQRT2; export { foo };
復(fù)制代碼在另一個(gè)模塊(腳本文件)中,我們可以像下面這樣引用:
import { cube, foo } from "my-module"; console.log(cube(3)); // 27 console.log(foo); // 4.555806215962888
使用默認(rèn)導(dǎo)出一個(gè)模塊時(shí):
// "my-module.js"模塊 export default function (x) { return x * x * x; }
復(fù)制代碼在另一個(gè)模塊(腳本文件)中,我們可以像下面這樣引用,相對(duì)名稱導(dǎo)出來(lái)說(shuō)使用更為簡(jiǎn)單:
// 引用 "my-module.js"模塊 import cube from "my-module"; console.log(cube(3)); // 27
import引入模塊
import語(yǔ)法聲明用于從已導(dǎo)出的模塊、腳本中導(dǎo)入函數(shù)、對(duì)象、指定文件(或模塊)的原始值。
import模塊導(dǎo)入與export模塊導(dǎo)出功能相對(duì)應(yīng),也存在兩種模塊導(dǎo)入方式:命名式導(dǎo)入(名稱導(dǎo)入)和默認(rèn)導(dǎo)入(定義式導(dǎo)入)。
import的語(yǔ)法跟require不同,而且import必須放在文件的最開(kāi)始,且前面不允許有其他邏輯代碼,這和其他所有編程語(yǔ)言風(fēng)格一致。
import defaultMember from "module-name"; import * as name from "module-name"; import { member } from "module-name"; import { member as alias } from "module-name"; import { member1 , member2 } from "module-name"; import { member1 , member2 as alias2 , [...] } from "module-name"; import defaultMember, { member [ , [...] ] } from "module-name"; import defaultMember, * as name from "module-name"; import "module-name";
name-從將要導(dǎo)入模塊中收到的導(dǎo)出值的名稱
member, memberN-從導(dǎo)出模塊,導(dǎo)入指定名稱的多個(gè)成員
defaultMember-從導(dǎo)出模塊,導(dǎo)入默認(rèn)導(dǎo)出成員
alias, aliasN-別名,對(duì)指定導(dǎo)入成員進(jìn)行的重命名
module-name-要導(dǎo)入的模塊。是一個(gè)文件名
as-重命名導(dǎo)入成員名稱(“標(biāo)識(shí)符”)
from-從已經(jīng)存在的模塊、腳本文件等導(dǎo)入
命名式導(dǎo)入
我們可以通過(guò)指定名稱,就是將這些成員插入到當(dāng)作用域中。導(dǎo)出時(shí),可以導(dǎo)入單個(gè)成員或多個(gè)成員:
注意,花括號(hào)里面的變量與export后面的變量一一對(duì)應(yīng)
import {myMember} from "my-module"; import {foo, bar} from "my-module";
通過(guò)*符號(hào),我們可以導(dǎo)入模塊中的全部屬性和方法。當(dāng)導(dǎo)入模塊全部導(dǎo)出內(nèi)容時(shí),就是將導(dǎo)出模塊(’my-module.js’)所有的導(dǎo)出綁定內(nèi)容,插入到當(dāng)前模塊(’myModule’)的作用域中:
import * as myModule from "my-module";
導(dǎo)入模塊對(duì)象時(shí),也可以使用as對(duì)導(dǎo)入成員重命名,以方便在當(dāng)前模塊內(nèi)使用:
import {reallyReallyLongModuleMemberName as shortName} from "my-module";
導(dǎo)入多個(gè)成員時(shí),同樣可以使用別名:
import {reallyReallyLongModuleMemberName as shortName, anotherLongModuleName as short} from "my-module";
導(dǎo)入一個(gè)模塊,但不進(jìn)行任何綁定:
import "my-module";
默認(rèn)導(dǎo)入
在模塊導(dǎo)出時(shí),可能會(huì)存在默認(rèn)導(dǎo)出。同樣的,在導(dǎo)入時(shí)可以使用import指令導(dǎo)出這些默認(rèn)值。
直接導(dǎo)入默認(rèn)值:
import myDefault from "my-module";
也可以在命名空間導(dǎo)入和名稱導(dǎo)入中,同時(shí)使用默認(rèn)導(dǎo)入:
import myDefault, * as myModule from "my-module"; // myModule 做為命名空間使用 或 import myDefault, {foo, bar} from "my-module"; // 指定成員導(dǎo)入
import使用示例
// --file.js-- function getJSON(url, callback) { let xhr = new XMLHttpRequest(); xhr.onload = function () { callback(this.responseText) }; xhr.open("GET", url, true); xhr.send(); } export function getUsefulContents(url, callback) { getJSON(url, data => callback(JSON.parse(data))); } // --main.js-- import { getUsefulContents } from "file"; getUsefulContents("http://itbilu.com", data => { doSomethingUseful(data); });
default關(guān)鍵字
// d.js export default function() {}
// 等效于:
function a() {}; export {a as default};
在import的時(shí)候,可以這樣用:
import a from "./d";
// 等效于,或者說(shuō)就是下面這種寫(xiě)法的簡(jiǎn)寫(xiě),是同一個(gè)意思
import {default as a} from "./d";
這個(gè)語(yǔ)法糖的好處就是import的時(shí)候,可以省去花括號(hào){}。
簡(jiǎn)單的說(shuō),如果import的時(shí)候,你發(fā)現(xiàn)某個(gè)變量沒(méi)有花括號(hào)括起來(lái)(沒(méi)有*號(hào)),那么你在腦海中應(yīng)該把它還原成有花括號(hào)的as語(yǔ)法。
所以,下面這種寫(xiě)法你也應(yīng)該理解了吧:
import $,{each,map} from "jquery";
import后面第一個(gè)}的替代寫(xiě)法。
as關(guān)鍵字
as簡(jiǎn)單的說(shuō)就是取一個(gè)別名,export中可以用,import中其實(shí)可以用:
// a.js var a = function() {}; export {a as fun}; // b.js import {fun as a} from "./a"; a();
上面這段代碼,export的時(shí)候,對(duì)外提供的接口是fun,它是a.js內(nèi)部a這個(gè)函數(shù)的別名,但是在模塊外面,認(rèn)不到a,只能認(rèn)到fun。
import中的as就很簡(jiǎn)單,就是你在使用模塊里面的方法的時(shí)候,給這個(gè)方法取一個(gè)別名,好在當(dāng)前的文件里面使用。之所以是這樣,是因?yàn)橛械臅r(shí)候不同的兩個(gè)模塊可能通過(guò)相同的接口,比如有一個(gè)c.js也通過(guò)了fun這個(gè)接口:
// c.js export function fun() {};
如果在b.js中同時(shí)使用a和c這兩個(gè)模塊,就必須想辦法解決接口重名的問(wèn)題,as就解決了。
CommonJS中module.exports 與 exports的區(qū)別
Module.exports
The module.exports object is created by the Module system. Sometimes this is not acceptable; many want their module to be an instance of some class. To do this, assign the desired export object to module.exports. Note that assigning the desired object to exports will simply rebind the local exports variable, which is probably not what you want to do.
譯文:module.exports對(duì)象是由模塊系統(tǒng)創(chuàng)建的。 有時(shí)這是難以接受的;許多人希望他們的模塊成為某個(gè)類的實(shí)例。 為了實(shí)現(xiàn)這個(gè),需要將期望導(dǎo)出的對(duì)象賦值給module.exports。 注意,將期望的對(duì)象賦值給exports會(huì)簡(jiǎn)單地重新綁定到本地exports變量上,這可能不是你想要的。
Module.exports
The exports variable is available within a module’s file-level scope, and is assigned the value of module.exports before the module is evaluated. It allows a shortcut, so that module.exports.f = … can be written more succinctly as exports.f = …. However, be aware that like any variable, if a new value is assigned to exports, it is no longer bound to module.exports:
譯文:exports變量是在模塊的文件級(jí)別作用域內(nèi)有效的,它在模塊被執(zhí)行前被賦于 module.exports 的值。它有一個(gè)快捷方式,以便 module.exports.f = … 可以被更簡(jiǎn)潔地寫(xiě)成exports.f = …。 注意,就像任何變量,如果一個(gè)新的值被賦值給exports,它就不再綁定到module.exports(其實(shí)是exports.屬性會(huì)自動(dòng)掛載到?jīng)]有命名沖突的module.exports.屬性)
從Api文檔上面的可以看出,從require導(dǎo)入方式去理解,關(guān)鍵有兩個(gè)變量(全局變量module.exports,局部變量exports)、一個(gè)返回值(module.exports)
function require(...) { var module = { exports: {} }; ((module, exports) => { // 你的被引入代碼 Start // var exports = module.exports = {}; (默認(rèn)都有的) function some_func() {}; exports = some_func; // 此時(shí),exports不再掛載到module.exports, // export將導(dǎo)出{}默認(rèn)對(duì)象 module.exports = some_func; // 此時(shí),這個(gè)模塊將導(dǎo)出some_func對(duì)象,覆蓋exports上的some_func // 你的被引入代碼 End })(module, module.exports); // 不管是exports還是module.exports,最后返回的還是module.exports return module.exports; } demo.js: console.log(exports); // {} console.log(module.exports); // {} console.log(exports === module.exports); // true console.log(exports == module.exports); // true console.log(module); /** Module { id: ".", exports: {}, parent: null, filename: "/Users/larben/Desktop/demo.js", loaded: false, children: [], paths: [ "/Users/larben/Desktop/node_modules", "/Users/larben/node_modules", "/Users/node_modules", "/node_modules" ] } */
注意:
每個(gè)js文件一創(chuàng)建,都有一個(gè)var exports = module.exports = {},使exports和module.exports都指向一個(gè)空對(duì)象。
module.exports和exports所指向的內(nèi)存地址相同
end~
本篇文章轉(zhuǎn)載自https://www.cnblogs.com/libin...
記得關(guān)注我的公眾號(hào),一起暴富!!!
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/104137.html
摘要:所有依賴這個(gè)模塊的語(yǔ)句,都定義在一個(gè)回調(diào)函數(shù)中,等到加載完成之后,這個(gè)回調(diào)函數(shù)才會(huì)運(yùn)行。目前,主要有兩個(gè)庫(kù)實(shí)現(xiàn)了規(guī)范和。這些導(dǎo)出對(duì)象用名稱進(jìn)行區(qū)分,稱之為命名式導(dǎo)出。 簡(jiǎn)單粗暴,富婆給你說(shuō),其實(shí)我也沒(méi)太搞明白,最近看了一篇文章我才理清了一點(diǎn)點(diǎn)思路,最近整日沉迷于肥宅快樂(lè)水,技術(shù)都跟不上了,來(lái)篇文章,提神醒腦,朝著我的富婆夢(mèng)更近一步,早日走上富婆路,包養(yǎng)我家大狼狗!!! 為什么有模塊概念...
摘要:如果這個(gè)模塊還依賴其他模塊,那么函數(shù)的第一個(gè)參數(shù),必須是一個(gè)數(shù)組,指明該模塊的依賴性。目前,主要有兩個(gè)庫(kù)實(shí)現(xiàn)了規(guī)范和。這些導(dǎo)出對(duì)象用名稱進(jìn)行區(qū)分,稱之為命名式導(dǎo)出。簡(jiǎn)單粗暴,富婆給你說(shuō),其實(shí)我也沒(méi)太搞明白,最近看了一篇文章我才理清了一點(diǎn)點(diǎn)思路,最近整日沉迷于肥宅快樂(lè)水,技術(shù)都跟不上了,來(lái)篇文章,提神醒腦,朝著我的富婆夢(mèng)更近一步,早日走上富婆路,包養(yǎng)我家大狼狗!!! 為什么有模塊概念 理想情況...
摘要:目前是沒(méi)有給我處理好權(quán)限這塊的邏輯。我們的項(xiàng)目正常是路由是在本地配置好的一個(gè)路由文件,所以,要想實(shí)現(xiàn)動(dòng)態(tài)的路由,我們就必須讓實(shí)現(xiàn)動(dòng)態(tài)生成。具體頁(yè)面上的按鈕權(quán)限的分配在前端頁(yè)面是怎么控制的,完全可以去里借鑒。 iview admin目前是沒(méi)有給我處理好權(quán)限這塊的邏輯。所以,權(quán)限這塊還是得我們自己去擼。(臉上笑嘻嘻、心里mmp!) 思路做權(quán)限,說(shuō)到底就是為了讓不同權(quán)限的用戶, 可以訪問(wèn)不...
摘要:所以你編譯后的文件實(shí)際上應(yīng)當(dāng)只輸出,這就需要在配置里用來(lái)控制這樣上面的模塊加載函數(shù)會(huì)在返回值后面加一個(gè),這樣就只返回的部分。 之前一篇文章分析了Webpack打包JS模塊的基本原理,所介紹的案例是最常見(jiàn)的一種情況,即多個(gè)JS模塊和一個(gè)入口模塊,打包成一個(gè)bundle文件,可以直接被瀏覽器或者其它JavaScript引擎執(zhí)行,相當(dāng)于直接編譯生成一個(gè)完整的可執(zhí)行的文件。不過(guò)還有一種很常見(jiàn)的...
摘要:因此,你還是需要各種各樣雜七雜八的工具來(lái)轉(zhuǎn)換你的代碼噢,我可去你媽的吧,這些東西都是干嘛的我就是想用個(gè)模塊化,我到底該用啥子本文正旨在列出幾種可用的在生產(chǎn)環(huán)境中放心使用模塊化的方法,希望能幫到諸位后來(lái)者這方面的中文資源實(shí)在是忒少了。 原文發(fā)表在我的博客上。最近搗鼓了一下 ES6 的模塊化,分享一些經(jīng)驗(yàn) :) Python3 已經(jīng)發(fā)布了九年了,Python 社區(qū)卻還在用 Python 2...
閱讀 3511·2023-04-25 14:57
閱讀 2560·2021-11-22 14:56
閱讀 2079·2021-09-29 09:45
閱讀 1761·2021-09-22 15:53
閱讀 3313·2021-08-25 09:41
閱讀 896·2019-08-29 15:22
閱讀 3289·2019-08-29 13:22
閱讀 3122·2019-08-29 13:08