摘要:本文從最簡(jiǎn)單的模塊開(kāi)始,然后主要從的模塊規(guī)范和的模塊機(jī)制對(duì)模塊進(jìn)行梳理。對(duì)象的屬性模塊的識(shí)別符,通常是帶有絕對(duì)路徑的模塊文件名。返回一個(gè)對(duì)象,表示調(diào)用該模塊的模塊。表示模塊對(duì)外輸出的值。可見(jiàn)當(dāng)刪除了相關(guān)模塊的緩存再一次加載時(shí)則不再有了。
前言
java有類(lèi)文件,Python有import機(jī)制,Ruby有require等,而Javascript 通過(guò)標(biāo)簽引入代碼的機(jī)制顯得雜亂無(wú)章,語(yǔ)言自身毫無(wú)組織能力,人們不得不用命名空間的等方式人為的組織代碼,以求達(dá)到安全易用的目的
《深入淺出Nodejs》--樸靈
模塊一直以來(lái)都是組織大型軟件的必備的要素,就像建筑和磚,“磚”的組織規(guī)則更是需要最先明確的事情,一直以來(lái)JS在語(yǔ)言層面都沒(méi)能給模塊機(jī)制足夠的重視,知道ES6的module的出現(xiàn)仿佛給出了最終解決的方案,但是畢竟ES6的module還沒(méi)能得到良好的支持,其中所面臨的復(fù)雜情況可想而知,因?yàn)闃I(yè)務(wù)場(chǎng)景的多樣性導(dǎo)致似乎哪一種模塊機(jī)制都感覺(jué)到了眾口難調(diào),雖然Node8已經(jīng)對(duì)絕大部分的ES6語(yǔ)法提供了非常好的支持,但是要想使用ES6的模塊機(jī)制還是必須要使用類(lèi)似babel的轉(zhuǎn)義工具才能做到并不是那么“無(wú)畏”的使用。本文從最簡(jiǎn)單的模塊開(kāi)始,然后主要從Node的模塊規(guī)范和ES6的模塊機(jī)制對(duì)模塊進(jìn)行梳理。
“模塊化”的基本實(shí)現(xiàn)每次在注冊(cè)成為某一個(gè)網(wǎng)站或者應(yīng)用的用戶時(shí)最讓人心碎的的就是自己常用的用戶名已經(jīng)存在了,很緊張得換了幾個(gè)還能接受的用戶名發(fā)現(xiàn)自己的想法總是很受歡迎,于是即便放著《不將就》也無(wú)奈的選擇了在自己的用戶名后面加上了自己的生日數(shù)字...
這里也不太方便討論如果加上了生日數(shù)字之后,表單校正還是提示你“該用戶名已經(jīng)存在!”的情況,剪網(wǎng)線就完事了。
我想表達(dá)的意思實(shí)際就是,全局環(huán)境下的變量的命名沖突,變量太多難免詞窮情況很常見(jiàn),所以這一定是模塊化給我們帶來(lái)的好處,有了模塊你就可以繼續(xù)用你喜歡的用戶名,只不過(guò)你得介紹清楚,你是“村口第五家.Ray"
無(wú)需多言,上圖表達(dá)了一切。良好的模塊化,是代碼復(fù)用與工程解耦的關(guān)鍵,"一把梭"確實(shí)爽,講究一個(gè)我不管你里面怎么翻滾,你暴露給我干凈的接口,我還你一個(gè)講究的git star。
如果一個(gè)包依賴(lài)另一個(gè)包,你一把梭的時(shí)候還要手動(dòng)先把它依賴(lài)的那個(gè)包梭進(jìn)來(lái),過(guò)分之,那個(gè)它依賴(lài)的包有依賴(lài)好幾個(gè)別的包,甚至有些情況中你甚至還要很在意你手動(dòng)添加依賴(lài)的順序,這種梭法,一旦項(xiàng)目復(fù)雜,光是對(duì)這些“梭法”的管理都讓人心煩了,所以為了省心,模塊機(jī)制也務(wù)必要面對(duì)解析依賴(lài),管理依賴(lài)這個(gè)本身就很繁瑣的任務(wù)。
所以進(jìn)入正題,針對(duì)前面提到的幾點(diǎn),看一看簡(jiǎn)單的模塊實(shí)現(xiàn)。
最簡(jiǎn)單的模塊化可以理解成一個(gè)一個(gè)的封裝函數(shù),每一個(gè)封裝的函數(shù)去完成特定的功能,調(diào)用函數(shù)的方式進(jìn)行復(fù)用。但是存在著類(lèi)似于a,b污染了全局變量的缺點(diǎn)
const module1 = ()=>{ // dosomething } const module2 = ()=>{ // dosomething }
使用對(duì)象封裝
var module1 = new Object({ _count : 0, m1 : function (){ //... }, m2 : function (){ //... } }); // module1.m1 // module1.m2
缺點(diǎn):往往存在不想讓外部訪問(wèn)的變量(module1._count),這種方式就不能滿足了(不考慮使用Object.defineProperty)
立即執(zhí)行函數(shù)的方式
var module1 = (function(){ var _count = 0; var m1 = function(){ //... }; var m2 = function(){ //... }; return { m1 : m1, m2 : m2 }; })();
通過(guò)自執(zhí)行函數(shù)可以只返回想返回的東西。
如果此模塊內(nèi)想繼承使用類(lèi)似于jquery等庫(kù)則就需要顯示的將庫(kù)傳入到自執(zhí)行函數(shù)中了
var module1 = (function ($, axios) { //... })(jQuery, axios);瀏覽器傳統(tǒng)加載模塊規(guī)則
1.默認(rèn)方法
通過(guò)標(biāo)簽加載 JavaScript 腳本,默認(rèn)是同步加載執(zhí)行的,渲染引擎如果遇到會(huì)停下來(lái),知道腳本下載執(zhí)行完成
2.異步方法
defer 和 async屬性
defer 會(huì)讓該標(biāo)簽引用的腳本在DOM完全解析之后,并且引用的其他腳本執(zhí)行完成之后,才會(huì)執(zhí)行;多個(gè)defer會(huì)按照在頁(yè)面上出現(xiàn)的順序依次執(zhí)行
async 類(lèi)似于異步回調(diào)函數(shù),加載完成或,渲染引擎就會(huì)立即停下來(lái)去執(zhí)行該腳本,多個(gè)async腳本不能后保證執(zhí)行的順序
CommonJsNode 的模塊系統(tǒng)就是參照著CommonJs規(guī)范所實(shí)現(xiàn)的
const path = require("path") path.join(__dirname,path.sep)
path.join 必然是依賴(lài)于path模塊加載完成才能使用的,對(duì)于服務(wù)器來(lái)說(shuō),因?yàn)樗械馁Y源都存放在本地,所以各種模塊各種模塊加載進(jìn)來(lái)之后再執(zhí)行先關(guān)邏輯對(duì)于速度的要求來(lái)說(shuō)并不會(huì)是那么明顯問(wèn)題。
特點(diǎn):
一個(gè)文件就是一個(gè)模塊,擁有多帶帶的作用域;
普通方式定義的變量、函數(shù)、對(duì)象都屬于該模塊內(nèi);
通過(guò)require來(lái)加載模塊;
通過(guò)exports和modul.exports來(lái)暴露模塊中的內(nèi)容;
模塊加載的順序,按照其在代碼中出現(xiàn)的順序。
模塊可以多次加載,但只會(huì)在第一次加載的時(shí)候運(yùn)行一次,然后運(yùn)行結(jié)果就被緩存了,以后再加載,就直接讀取緩存結(jié)果;模塊的加載順序,按照代碼的出現(xiàn)順序是同步加載的;
require(同步加載)基本功能:讀取并執(zhí)行一個(gè)JS文件,然后返回該模塊的exports對(duì)象,如果沒(méi)有發(fā)現(xiàn)指定模塊會(huì)報(bào)錯(cuò);
exports:node為每個(gè)模塊提供一個(gè)exports變量,其指向module.exports,相當(dāng)于在模塊頭部加了這句話:var exports = module.exports,在對(duì)外輸出時(shí),可以給exports對(duì)象添加方法(exports.xxx等同于module.exports.xxx),不能直接賦值(因?yàn)檫@樣就切斷了exports和module.exports的聯(lián)系);
module變量代表當(dāng)前模塊。這個(gè)變量是一個(gè)對(duì)象,它的exports屬性(即module.exports)是對(duì)外的接口。加載某個(gè)模塊,其實(shí)是加載該模塊的module.exports屬性。
module對(duì)象的屬性:
module.id模塊的識(shí)別符,通常是帶有絕對(duì)路徑的模塊文件名。
module.filename 模塊的文件名,帶有絕對(duì)路徑。
module.loaded 返回一個(gè)布爾值,表示模塊是否已經(jīng)完成加載。
module.parent 返回一個(gè)對(duì)象,表示調(diào)用該模塊的模塊。
module.children 返回一個(gè)數(shù)組,表示該模塊要用到的其他模塊。
module.exports 表示模塊對(duì)外輸出的值。
例子:
注意在這種方式下module.exports被重新賦值了,所以之前使用exports導(dǎo)出的hello不再有效(模塊頭部var exports = module.exports)
exports.hello = function() { return "hello"; }; module.exports = "Hello world";/
因此一旦module.exports被賦值了,表明這個(gè)模塊具有單一出口了
AMDAsynchronous Module Definition異步加載某模塊的規(guī)范。試想如果在瀏覽器中(資源不再本地)采用commonjs這種完全依賴(lài)于先加載再試用方法,那么如果一個(gè)模塊特別大,網(wǎng)速特別慢的情況下就會(huì)出現(xiàn)頁(yè)面卡頓的情況。便有了異步加載模塊的AMD規(guī)范。require.js便是基于此規(guī)范
require(["module1","module2"....], callback); reqire([jquery],function(jquery){ //do something }) //定義模塊 define(id, [depends], callback); //id是模塊名,可選的依賴(lài)別的模塊的數(shù)組,callback是用于return出一個(gè)給別的模塊用的函數(shù)
熟悉的回調(diào)函數(shù)形式。
Node的模塊實(shí)現(xiàn)Node 對(duì)于模塊的實(shí)現(xiàn)以commonjs為基礎(chǔ)的同時(shí)也增加了許多自身的特性
Node模塊的引入的三個(gè)步驟
路徑分析
文件定位
在require參數(shù)中如果不寫(xiě)后綴名,node會(huì)按照.js,.node,.json的順序依次補(bǔ)足并try
此過(guò)程會(huì)調(diào)用fs模塊同步阻塞式的判斷文件是否存在,因此非js文件最后加上后綴
編譯執(zhí)行
.js 文件會(huì)被解析為 JavaScript 文本文件,.json 文件會(huì)被解析為 JSON 文本文件。 .node 文件會(huì)被解析為通過(guò) dlopen 加載的編譯后的插件模塊.
Node的模塊分類(lèi)
核心模塊 Node本身提供的模塊,比如path,buffer,http等,在Node編譯過(guò)程中就加載進(jìn)內(nèi)存,因此會(huì)省掉文件定位和編譯執(zhí)行兩個(gè)文件加載步驟
文件模塊 開(kāi)發(fā)人員自己寫(xiě)的模塊,會(huì)經(jīng)歷完整的模塊引入步驟
Node也會(huì)優(yōu)先從緩存中加載引入過(guò)的文件模塊,在Node中第一次加載某一個(gè)模塊的時(shí)候,Node就會(huì)緩存下該模塊,之后再加載模塊就會(huì)直接從緩存中取了。這個(gè)“潛規(guī)則”核心模塊和文件模塊都會(huì)有。
require("./test.js").message="hello" console.log(require.cache); console.log(require("./test.js").message)//hello
上述代碼說(shuō)明第二次加載依舊使用了第一次加載進(jìn)來(lái)之后的模塊并沒(méi)有重新加載而是讀取了緩存中的模塊,因?yàn)橹匦录虞d的某塊中并沒(méi)有message。打印出來(lái)的require.cache包含了本模塊的module信息和加載進(jìn)來(lái)的模塊信息。
那么如果你想要多次執(zhí)行某一個(gè)模塊,要么你手動(dòng)像下面這樣刪除該模塊的緩存記錄之后再重新加載使用,要么應(yīng)該在模塊中暴露一個(gè)工廠函數(shù),然后調(diào)用那個(gè)函數(shù)多次執(zhí)行該模塊,與vue-ssr的創(chuàng)建應(yīng)用實(shí)例的工廠函數(shù)意思相近。
require("./test.js").message="hello" delete require.cache["/absolute-path/test.js"] console.log(require("./test.js").message)//undifined
可見(jiàn)當(dāng)刪除了相關(guān)模塊的緩存,再一次加載時(shí)則不再有message了。
// Vue-ssr工廠函數(shù),目的是為每個(gè)請(qǐng)求創(chuàng)立一個(gè)新的應(yīng)用實(shí)例 const Vue = require("vue") module.exports = function createApp (context) { return new Vue({ data: { url: context.url }, template: `訪問(wèn)的 URL 是: {{ url }}` }) }
模塊包裝器
Node在加載模塊之后,執(zhí)行之前則會(huì)使用函數(shù)包裝器將模塊代碼包裝,從而實(shí)現(xiàn)將頂層變量(var,let,const)作用域限制在模塊范圍內(nèi),提供每一個(gè)特定在該模塊的頂層全局變量module,exports,__dirname(所在文件夾的絕對(duì)路徑),__filename(絕對(duì)路徑加上文件名)
(function(exports, require, module, __filename, __dirname) { // 模塊的代碼實(shí)際上在這里 });
關(guān)于模塊的具體編譯執(zhí)行過(guò)程,這次就不深入討論了,足夠花心思在好好重新深入總結(jié)重寫(xiě)一篇了,順便再次安利樸靈大大的《深入淺出nodejs》
ES6中模塊的解決方案終于,ES6在語(yǔ)言層面上提供了JS一直都沒(méi)有的模塊功能,使得在繼Commonjs之于服務(wù)端,AMD之于瀏覽器之外提供了一個(gè)通用的解決方案。
1.設(shè)計(jì)思想
盡量靜態(tài)化(靜態(tài)加載),使得編譯時(shí)就能確定模塊間的依賴(lài)關(guān)系以及輸入輸出的變量。
2.關(guān)鍵語(yǔ)法
export
export可以輸出變量:export var a = 1
輸出函數(shù):`export function sum(x, y) {
return x + y;
};
`
輸出類(lèi):export class A{}
結(jié)尾大括號(hào)寫(xiě)法:export {a , sum , A}
尤為注意的一點(diǎn)就是export所導(dǎo)出的接口一定要和模塊內(nèi)部的變量建立一一對(duì)應(yīng)的關(guān)系
對(duì)于一個(gè)模塊來(lái)說(shuō),它就是一個(gè)默認(rèn)使用了嚴(yán)格模式的文件("use strict"),而別的文件要想使用該模塊,就必須要求該模塊內(nèi)有export主動(dòng)導(dǎo)出的內(nèi)容
例子:
export 1 //直接導(dǎo)出一個(gè)數(shù)字是不可以的 var a= 2 export a //間接導(dǎo)出數(shù)字也是不可以的! export {a}//正確 export function(){} //錯(cuò)誤 function sum(){} export sum //錯(cuò)誤 export {sum}//正確
export個(gè)人最為重要的一點(diǎn)就是可以取到模塊內(nèi)的實(shí)時(shí)的值
例子:
export var foo = "bar"; setTimeout(() => foo = "baz", 500);
引用該模塊的文件在定時(shí)器時(shí)間到的時(shí)候則會(huì)得到改變后的值
export default
實(shí)質(zhì): 導(dǎo)出一個(gè)叫做default(默認(rèn)的)變量,本質(zhì)是將后面的值,賦給default變量,所以情況就和export 不同了
不同點(diǎn):
export 導(dǎo)出的變量,在import的時(shí)候必須要知道變量名,否則無(wú)法加載,export default就允許隨意取名直接加載,并且不用使用大括號(hào);
export default 后面不能跟變量聲明語(yǔ)句
// 第一組 export default function crc32() {} import crc32 from "crc32"; // 輸入 // 第二組 export function crc32() {}; import {crc32} from "crc32"; // 輸入 export var a = 1;// 正確 var a = 1; export default a;// 正確 export default var a = 1;// 錯(cuò)誤
export default 每一個(gè)模塊只允許有一個(gè)
import
與導(dǎo)出export對(duì)應(yīng),引用則是import
export {a,b} || / import { a as A ,b as B} from "./test.js";
主要特點(diǎn):
使用import加載具有提升的效果,即會(huì)提到文件頭部進(jìn)行:
foo(); import { foo } from "my_module";
該代碼會(huì)正常執(zhí)行。
*加載默認(rèn)加載全部導(dǎo)出的變量
import * as A from "./a.js"
import 加載進(jìn)來(lái)的變量是不允許改變的。
瀏覽器對(duì)ES6模塊的加載type="module",此時(shí)瀏覽器就會(huì)知道這是ES6模塊,同時(shí)會(huì)自動(dòng)給他加上前文提到的defer屬性,即等到所有的渲染操作都執(zhí)行完成之后,才會(huì)執(zhí)行該模塊
Node 對(duì)ES6模塊的加載
由于Node有自己的模塊加載機(jī)制,所以在Node8.5以上版本將兩種方式的加載分開(kāi)來(lái)處理,對(duì)于加載ES6的模塊,node要求其后綴名得是.mjs,然后還得加上--experimental-modules參數(shù),然后兩種機(jī)制還不能混用。確實(shí)還是很麻煩的,所以現(xiàn)在Node端想用import主流還是用babel轉(zhuǎn)義。
對(duì)比ES6 module和Node的commonjs 差異:靜態(tài)加載VS運(yùn)行時(shí)加載
首先看下面一段代碼:
if (x > 2) { import A from "./a.js"; }else{ import B from "./b.js"; }
這段代碼會(huì)報(bào)錯(cuò),因?yàn)镴S引擎在處理import是在編譯時(shí)期,此時(shí)不會(huì)去執(zhí)行條件語(yǔ)句,因此這段代碼會(huì)出現(xiàn)句法錯(cuò)誤,相反,如果換成:
if (x > 2) { const A =require("./a.js"); }else{ const B =require("./b.js"); }
commonjs是在運(yùn)行時(shí)加載模塊,因此上面代碼就會(huì)成功運(yùn)行
由于動(dòng)態(tài)加載功能的要求,才會(huì)有了import()函數(shù)的提案,這里就不過(guò)多贅述。
值的引用VS值的拷貝
commonjs模塊在加載之后會(huì)把原始類(lèi)型的值緩存,之后該模塊的內(nèi)部變化則不會(huì)再影響到其輸出的值:
//test.js var counter = 3; function incCounter() { counter++; } module.exports = { counter: counter, incCounter: incCounter, }; ================================== //main.js var test = require("./test"); console.log(test.counter); // 3 test.incCounter(); console.log(test.counter); // 3
ES6的模塊機(jī)制,在引擎靜態(tài)分析階段會(huì)把import當(dāng)成是一種只讀引用(地址是只讀的const,因此不可以在引用該模塊的文件里給他重新賦值),等到代碼實(shí)際運(yùn)行時(shí),才會(huì)根據(jù)引用去取值
// test.js export let counter = 3; export function incCounter() { counter++; } // main.js import { counter, incCounter } from "./test"; console.log(counter); // 3 incCounter(); console.log(counter); // 4循環(huán)加載問(wèn)題
循環(huán)加載指的是,a文件依賴(lài)于b文件,而b文件又依賴(lài)于a文件
commonjs的循環(huán)加載問(wèn)題
commonjs是在加載時(shí)執(zhí)行的,他在require的時(shí)候就會(huì)全部跑一遍,因此他在遇到循環(huán)加載的情況就會(huì)只輸出已經(jīng)執(zhí)行的部分,而之后的部分則不會(huì)輸出,下面是一個(gè)例子:
//parent文件 exports.flag = 1; let children = require("./children")//停下來(lái),加載chilren console.log(`parent文件中chilren的flag =${children.flag}`); exports.flag = 2 console.log(`parent文件執(zhí)行完畢了`); ========================================================= //test2文件 exports.flag = 1; let parent = require("./parent")//停下來(lái),加載parent,此時(shí)parent只執(zhí)行到了第一行,導(dǎo)出結(jié)果flag ==1 console.log(`children文件中parent的flag =${parent.flag}`); exports.flag = 2 console.log(`children文件執(zhí)行完畢了`);
node parent之后運(yùn)行結(jié)果為
運(yùn)行parent之后會(huì)在第一行導(dǎo)出flag=1,然后去ruquirechildren文件,此時(shí)parent進(jìn)行等待,等待children文件執(zhí)行結(jié)束,children開(kāi)始執(zhí)行到第二行的時(shí)候出現(xiàn)“循環(huán)加載”parent文件,此時(shí)系統(tǒng)自動(dòng)去找parent文件的exports屬性,而parent只執(zhí)行了一行,但是好在它有exports了flag,所以children文件加再進(jìn)來(lái)了那個(gè)flag并繼續(xù)執(zhí)行,第三行不會(huì)報(bào)錯(cuò),最后在第四行children導(dǎo)出了flag=2,此時(shí)parent再接著執(zhí)行到結(jié)束。
ES6中的循環(huán)加載問(wèn)題
ES6和commonjs本質(zhì)上不同!因?yàn)镋S6是引用取值,即動(dòng)態(tài)引用
引用阮一峰老師ES6標(biāo)準(zhǔn)入門(mén)的例子
// a.mjs import {bar} from "./b"; console.log("a.mjs"); console.log(bar); export let foo = "foo"; // b.mjs import {foo} from "./a"; console.log("b.mjs"); console.log(foo); export let bar = "bar";
執(zhí)行后的結(jié)果:
執(zhí)行的過(guò)程是當(dāng)a文件防線import了b文件之后就會(huì)去執(zhí)行b文件,到了b文件這邊看到了他又引用了a文件,并不會(huì)又去執(zhí)行a文件發(fā)生“張郎送李郎”的故事,而是倔強(qiáng)得認(rèn)為foo這個(gè)接口已經(jīng)存在了,于是就繼續(xù)執(zhí)行下去,直到在要引用foo的時(shí)候發(fā)現(xiàn)foo還沒(méi)有定義,因?yàn)閘et定義變量會(huì)出現(xiàn)"暫時(shí)性死區(qū)",不可以還沒(méi)定義就使用,其實(shí)如果改成var聲明,有個(gè)變量提升作用就不會(huì)報(bào)錯(cuò)了。改成var聲明fooexport let foo = "foo";
雖然打印的foo是undifined但是并沒(méi)有影響程序執(zhí)行,但最好的做法是,改成同樣有提升作用的function來(lái)聲明。最后去執(zhí)行函數(shù)來(lái)獲得值,最后得到了希望的結(jié)果
// a.mjs import {bar} from "./b"; console.log("a.mjs"); console.log(bar()); export function foo() { return "foo" }; // b.mjs import {foo} from "./a"; console.log("b.mjs"); console.log(foo()); export function bar() { return "bar" };結(jié)束語(yǔ)
其實(shí)關(guān)于模塊還有很多東西還沒(méi)有梳理總結(jié)到,比如node模塊的加載過(guò)程的細(xì)節(jié),和編譯過(guò)程,再比如如何自己寫(xiě)一個(gè)npm模塊發(fā)布等等都是很值得去梳理總結(jié)的,這一次就先到這吧,總之,第一次在自己的SF正兒八經(jīng)的寫(xiě)這么長(zhǎng)的技術(shù)總結(jié)博客,組織內(nèi)容上感覺(jué)比較凌亂,還有很多的不足。希望自己以后多多總結(jié)提高吧。最后當(dāng)然還是要感謝開(kāi)源,感謝提供了那么多優(yōu)秀資料的前輩們。也歡迎來(lái)我的博客網(wǎng)站(https://isliulei.com)指教。
參考文章:
ES6標(biāo)準(zhǔn)入門(mén)--阮一峰
Nodejs v8.9.4 官方文檔
《深入淺出Nodejs》---樸靈
Commonjs規(guī)范
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/92818.html
摘要:插件開(kāi)發(fā)前端掘金作者原文地址譯者插件是為應(yīng)用添加全局功能的一種強(qiáng)大而且簡(jiǎn)單的方式。提供了與使用掌控異步前端掘金教你使用在行代碼內(nèi)優(yōu)雅的實(shí)現(xiàn)文件分片斷點(diǎn)續(xù)傳。 Vue.js 插件開(kāi)發(fā) - 前端 - 掘金作者:Joshua Bemenderfer原文地址: creating-custom-plugins譯者:jeneser Vue.js插件是為應(yīng)用添加全局功能的一種強(qiáng)大而且簡(jiǎn)單的方式。插....
摘要:一概述集合是引入的新的內(nèi)置對(duì)象類(lèi)型,其特點(diǎn)同數(shù)學(xué)意義的集合,即集合內(nèi)所有元素不重復(fù)元素唯一。數(shù)組集合對(duì)比數(shù)組和集合,數(shù)組可以加入重復(fù)數(shù)據(jù),而集合的所有元素是唯一的不允許重復(fù)。因此,適合臨時(shí)存放一組對(duì)象,以及存放跟對(duì)象綁定的信息。 本文同步帶你入門(mén) 帶你入門(mén) JavaScript ES6 (五) 集合,轉(zhuǎn)載請(qǐng)注明出處。 前面我們學(xué)習(xí)了: for of 變量和擴(kuò)展語(yǔ)法 塊作用域變量和解構(gòu)...
摘要:引擎對(duì)堆內(nèi)存中的對(duì)象進(jìn)行分代管理新生代存活周期較短的對(duì)象,如臨時(shí)變量字符串等。內(nèi)存泄漏對(duì)于持續(xù)運(yùn)行的服務(wù)進(jìn)程,必須及時(shí)釋放不再用到的內(nèi)存。 (關(guān)注福利,關(guān)注本公眾號(hào)回復(fù)[資料]領(lǐng)取優(yōu)質(zhì)前端視頻,包括Vue、React、Node源碼和實(shí)戰(zhàn)、面試指導(dǎo)) 本周正式開(kāi)始前端進(jìn)階的第一期,本周的主題是調(diào)用堆棧,今天是第4天。 本計(jì)劃一共28期,每期重點(diǎn)攻克一個(gè)面試重難點(diǎn),如果你還不了解本進(jìn)階計(jì)劃...
摘要:模塊化是隨著前端技術(shù)的發(fā)展,前端代碼爆炸式增長(zhǎng)后,工程化所采取的必然措施。目前模塊化的思想分為和。特別指出,事件不等同于異步,回調(diào)也不等同于異步。將會(huì)討論安全的類(lèi)型檢測(cè)惰性載入函數(shù)凍結(jié)對(duì)象定時(shí)器等話題。 Vue.js 前后端同構(gòu)方案之準(zhǔn)備篇——代碼優(yōu)化 目前 Vue.js 的火爆不亞于當(dāng)初的 React,本人對(duì)寫(xiě)代碼有潔癖,代碼也是藝術(shù)。此篇是準(zhǔn)備篇,工欲善其事,必先利其器。我們先在代...
摘要:談起閉包,它可是兩個(gè)核心技術(shù)之一異步基于打造前端持續(xù)集成開(kāi)發(fā)環(huán)境本文將以一個(gè)標(biāo)準(zhǔn)的項(xiàng)目為例,完全拋棄傳統(tǒng)的前端項(xiàng)目開(kāi)發(fā)部署方式,基于容器技術(shù)打造一個(gè)精簡(jiǎn)的前端持續(xù)集成的開(kāi)發(fā)環(huán)境。 這一次,徹底弄懂 JavaScript 執(zhí)行機(jī)制 本文的目的就是要保證你徹底弄懂javascript的執(zhí)行機(jī)制,如果讀完本文還不懂,可以揍我。 不論你是javascript新手還是老鳥(niǎo),不論是面試求職,還是日...
閱讀 1994·2021-09-26 10:19
閱讀 3268·2021-09-24 10:25
閱讀 1657·2019-12-27 11:39
閱讀 1938·2019-08-30 15:43
閱讀 683·2019-08-29 16:08
閱讀 3515·2019-08-29 16:07
閱讀 915·2019-08-26 11:30
閱讀 1280·2019-08-26 10:41