摘要:既然這樣,怎么理解中的單線程再捋一捋和的關(guān)系。在線程上,不會(huì)等待操作完成,繼續(xù)執(zhí)行后續(xù)的代碼。這就是單線程異步。在中除了代碼,一切都是并行的由于中主任務(wù)的執(zhí)行是以單線程的方式進(jìn)行,如果程序出錯(cuò)導(dǎo)致崩潰,就會(huì)終止整個(gè)流程。
node是什么
第一句話Node.js 是一個(gè)基于 Chrome V8 引擎的 JavaScript 運(yùn)行環(huán)境。
Node.js 使用了一個(gè)事件驅(qū)動(dòng)、非阻塞式 I/O 的模型。
Node使用包管理器NPM。
Node.js 是一個(gè)基于 Chrome V8 引擎的 JavaScript 運(yùn)行環(huán)境。
運(yùn)行環(huán)境, 不是一門語(yǔ)言,不是一個(gè)框架。只是能夠作為JavaScript代碼運(yùn)行的一個(gè)環(huán)境。
而這個(gè)運(yùn)行環(huán)境主要是由V8提供的。
V8做了什么?創(chuàng)建了一個(gè)callstack。
function main(){ func1(); } function func1(){ func2(); } function func2(){ console.log(1); } main();除去V8,Node中還有哪些東西?
除去V8,Node中另外一個(gè)比較重要的組成就是 libuv。
What? libuv是什么鬼?
先說(shuō)說(shuō),關(guān)于Node的另外一句話:
Node is designed to build scalable network applications.
這句話的底氣在哪兒,就是Node本身采用的 事件驅(qū)動(dòng),非阻塞I/O模型。
在 并發(fā)模型構(gòu)建網(wǎng)絡(luò)的應(yīng)用中,每個(gè)連接都會(huì)生成一個(gè)新線程,每個(gè)新線程可能需要 2MB 的配套內(nèi)存。在一個(gè)擁有 8 GB RAM 的系統(tǒng)上,理論上最大的并發(fā)連接數(shù)量是 4,000 個(gè)用戶。隨著您的客戶群的增長(zhǎng),如果希望您的 Web 應(yīng)用程序支持更多用戶,那么,您必須添加更多服務(wù)器。所以在傳統(tǒng)的后臺(tái)開發(fā)中,整個(gè) Web 應(yīng)用程序架構(gòu)(包括流量、處理器速度和內(nèi)存速度)中的瓶頸是:服務(wù)器能夠處理的并發(fā)連接的最大數(shù)量。這個(gè)不同的架構(gòu)承載的并發(fā)數(shù)量是不一致的。而且,多個(gè)線程存在的話,也會(huì)衍生出線程切換的問(wèn)題,這也會(huì)占用一定資源。
并發(fā)存在的兩個(gè)問(wèn)題:
Execution stacks take up memory: 資源有限
Context switching is not free:占用額外資源
Node的解決這個(gè)問(wèn)題思路:
在網(wǎng)絡(luò)應(yīng)用中,比較慢的環(huán)節(jié)主要在 磁盤讀取 或 網(wǎng)絡(luò)請(qǐng)求階段,這時(shí)候CPU處于閑置狀態(tài)。
如果在等待I/O操作時(shí),能夠釋放處于閑置狀態(tài)的CPU,則可以很大程度上利用資源;
那么接下來(lái)的問(wèn)題就在于,如何在I/O 操作完成后,繼續(xù)執(zhí)行后續(xù)的操作;
解決方案:事件驅(qū)動(dòng),采用回調(diào)。這和瀏覽器中的Event Loop是一樣的道理。
市場(chǎng)上已經(jīng)有一些使用同樣處理思路的框架。
EventMachine:處理網(wǎng)絡(luò)請(qǐng)求的框架,主要是面向ruby;
Twisted:用Python實(shí)現(xiàn)的基于事件驅(qū)動(dòng)的網(wǎng)絡(luò)引擎框架;
具體是怎么做的?
在程序運(yùn)行時(shí),V8 會(huì)把I/O操作等耗時(shí)較多操作及相關(guān)回調(diào)一并交給libuv去處理。而V8繼續(xù)執(zhí)行后面的代碼。等到I/O操作完成后,libuv會(huì)將回調(diào)方法放到事件隊(duì)列中。
const fs = require("fs"); const readFile = (file) => { fs.readFile(file, (err, data) => { if(!err) console.log(data); }); } console.log("program start ......"); readFile("file.json"); console.log("readFile has put the I/O "); console.log("program end!!!!!");
負(fù)責(zé)異步程序調(diào)度的工作就是libuv做的事情。
Libuv is a multi-platform support library with a focus on asynchronous I/O.
在上述程序中,當(dāng)遇到文件讀取操作時(shí),V8會(huì)把js接口轉(zhuǎn)成C++接口 同時(shí)把回調(diào)方法一并交給libvu。此時(shí)libuv接管這個(gè)文件讀取任務(wù)。當(dāng)文件讀取完成后,libuv就會(huì)把這個(gè)事件的回調(diào)函數(shù)扔到事件隊(duì)列里。當(dāng)下一次檢查事件隊(duì)列時(shí),就會(huì)執(zhí)行該回調(diào)函數(shù)。
question: 既然這樣,怎么理解node中的單線程?
再捋一捋Node, V8 和libuv的關(guān)系。
1) Node主要由V8 javascript引擎和libuv組成;
2) v8引擎主要負(fù)責(zé)解釋執(zhí)行js代碼,碰到需要異步的操作會(huì)交給libuv處理;
3) libuv本身是獨(dú)立的c語(yǔ)言庫(kù),可以直接使用c/c++來(lái)調(diào)用;
在瀏覽器端,JS是沒(méi)有能力進(jìn)行文件讀取操作的。js最初的能力也就限制在表單校驗(yàn)上。而在Node中,JS可以操作本地文件,建立網(wǎng)絡(luò)連接。這肯定是Node干的好事!
再來(lái)說(shuō)說(shuō)Node中其它一些組成部分
Node擴(kuò)展了JS的能力:builtin modulesbuiltin modules是由C++代碼寫成各類模塊,包含了crypto,zlib, file, net等基礎(chǔ)功能。
native modules除了builtin modules, 還有一個(gè)native modules。它們是用js編寫的內(nèi)建模塊,提供給程序開發(fā)者使用。
fs
http
builtin modules 和 native modules都屬于核心模塊。核心模塊在Node源碼編譯的過(guò)程中,編譯進(jìn)了二進(jìn)制文件。所以在Node進(jìn)程啟動(dòng)的時(shí)候,部分核心模塊就已經(jīng)被直接加載到了內(nèi)存當(dāng)中。
至此,Node的基本構(gòu)成和運(yùn)行原理已經(jīng)講完了。
補(bǔ)充一句:Node.js的單線程并不是真正的單線程,只是開啟了單個(gè)線程(可以定義為主線程)進(jìn)行業(yè)務(wù)處理,同時(shí)開啟了其他線程專門處理I/O。當(dāng)一個(gè)指令到達(dá)主線程,主線程發(fā)現(xiàn)有I/O之后,直接把這個(gè)事件傳給libuv處理。libuv會(huì)管理一個(gè)線程池,I/O操作就是由線程池里面的線程完成的。等I/O 操作完成,libuv,會(huì)把對(duì)應(yīng)I/O操作的回調(diào)放到事件循環(huán)當(dāng)中。在線程上,不會(huì)等待I/O 操作完成,繼續(xù)執(zhí)行后續(xù)的代碼。這就是“單線程”、“異步I/O”。
IO.js
var fork = require("child_process").fork; var fs = require("fs"); console.log("start......"); // blocking // console.log(fs.readFileSync("test.json", "utf-8")); // non blocking var childProcess = fork("another-thread.js"); childProcess.on("message", function(data){ console.log(data); }) console.log("end !!!");
another-child.js
var fs = require("fs"); process.send( fs.readFileSync("test.json", "utf-8"));
Everything runs in parallel except your code! 在Node中)除了代碼,一切都是并行的!
由于node中主任務(wù)的執(zhí)行是以單線程的方式進(jìn)行,如果程序出錯(cuò)導(dǎo)致崩潰,就會(huì)終止整個(gè)流程。為此,市場(chǎng)上有些Node進(jìn)程管理工具,它們會(huì)維護(hù)Node程序的狀態(tài),當(dāng)程序掛掉時(shí),會(huì)自動(dòng)重啟。比如我們使用的pm2。
NPM對(duì)于node沒(méi)有的一些模塊(native modules),可以引入外部模塊。這些外部模塊通常是其它開發(fā)者貢獻(xiàn)的。
那么問(wèn)題來(lái)了,對(duì)于數(shù)量眾多的模塊中,如何快速找到自己想要的并能夠快速的引進(jìn)到自己的項(xiàng)目當(dāng)中。
這就是npm幫我們做的工作。
Use npm to install, share, and distribute code; manage dependencies in your projects; and share & receive feedback with others.
npm官網(wǎng)
模塊安裝:
模塊共享
發(fā)布代碼
管理依賴
共享和反饋
NPM的基本模式NPM是JavaScript包的管理器。
廣義的npm的構(gòu)成npm consists of three distinct components:
the website: NPM官方站點(diǎn)
the Command Line Interface (CLI) : NPM命令行工具
the registry: JS模塊的數(shù)據(jù)庫(kù)
Use the website to discover packages, set up profiles, and manage other aspects of your npm experience. For example, you can set up Orgs (organizations) to manage access to public or private packages.
The CLI runs from a terminal. This is how most developers interact with npm.
The registry is a large public database of JavaScript software and the meta-information surrounding it.
npm中的使用npm默認(rèn)隨node一起安裝,在Node安裝完成后,npm已經(jīng)安裝。
查找一個(gè)包去npm官網(wǎng),按關(guān)鍵詞查找。
管理模塊npm install [module name] :普通安裝方式,包安裝完成后,會(huì)在當(dāng)前目錄生成一個(gè)node_modules目錄。這是一個(gè)存放外部js模塊的地方,通過(guò)npm安裝的包都放在node_modules下。
npm install -g [module name]:全局安裝,模塊被安裝在node安裝路徑下的 node_modules中。
npm install [folder path]:可以指定npm 安裝某個(gè)目錄folder path下的的文件,前提是這個(gè)目錄下包含package.json文件。
npm install [module name]@[version]: 安裝包的時(shí)候,指定對(duì)應(yīng)的版本號(hào)。
npm isntall chalk@latest : 安裝最新版
npm install [email protected]: 安裝2.0.0版
npm install chalk@">=2.0.0":安裝大于2.0.0的版本
npm install --save-prod [module name]: 在本地安裝包,并將安裝信息寫入 package.json文件中的dependencies中, 不寫--save-prod 或者只寫 --save 默認(rèn)跟 --save-prod一樣。
npm install --save-dev [module name]:在本地安裝包,并將安裝信息寫入 package.json文件中的devDependencies中
dependencies:在生產(chǎn)環(huán)境中需要用到的依賴
devDependencies:在開發(fā)、測(cè)試環(huán)境中用到的依賴
npm update [module name]: 更新本地模塊
npm uninstall [module name]: 卸載模塊
package.jsonpackage.json是一個(gè)node和npm都會(huì)自動(dòng)讀取的配置文件,它里面是個(gè)標(biāo)準(zhǔn)的JSON格式字符串。
對(duì)于NPM而言, package.json做了以下工作:
存儲(chǔ)項(xiàng)目依賴的所有包
允許你指定項(xiàng)目依賴的包的版本規(guī)則,不滿足項(xiàng)目需求的版本,不需要
讓你的項(xiàng)目構(gòu)建具有可復(fù)用性,容易分享你的項(xiàng)目
對(duì)于你的項(xiàng)目而言,package.json定義了一些基礎(chǔ)信息,比如項(xiàng)目名稱,版本等等。
pakcage.json必須具有的兩個(gè)字段: name 和 version。這倆個(gè)字段有什么意義呢?
NPM 作為一個(gè)包管理平臺(tái),當(dāng)有開發(fā)者提交(publish)模塊時(shí),必須提供一些基本信息便于管理。
name: 項(xiàng)目名稱或者模塊名稱
version:版本號(hào),應(yīng)當(dāng)遵循 x.x.x的格式
description:項(xiàng)目信息描述,方便別人了解你的模塊,也利于搜索
keywords:項(xiàng)目的關(guān)鍵詞,便于搜索
homepage:項(xiàng)目的主頁(yè);
scripts:scripts屬性是一個(gè)對(duì)象,里面的每一個(gè)屬性對(duì)應(yīng)一段腳本;腳本可以使用 npm run + 屬性名 執(zhí)行
main:指定項(xiàng)目的程序入口文件,該文件的exports對(duì)象同時(shí)也是require項(xiàng)目時(shí),取到的對(duì)象。
repository:指明代碼存在的地址,便于別人更好的查看你的源碼
dependencies:一個(gè)對(duì)象,配置模塊依賴的模塊列表,key是模塊名稱,value是版本描述(遵循semantic規(guī)則)
devDependencies:一個(gè)對(duì)象,開發(fā)或測(cè)試過(guò)程中的一些依賴模塊,跟上線后的依賴模塊區(qū)分出來(lái)
engines: 指定項(xiàng)目運(yùn)行的Node版本
author:項(xiàng)目的開發(fā)者
contributors:一堆項(xiàng)目的開發(fā)者
{ "name": "vue-todo", "version": "1.0.0", "description": "a simply todolist using vuejs", "scripts": { "start": "node server.js", "stop": "egg-scripts stop --title=egg-server-example", "dev": "egg-bin dev" }, "dependencies": { // 線上生產(chǎn)環(huán)境必須,當(dāng)然開發(fā)環(huán)境也會(huì)用到 "babel-runtime": "^6.23.0", "vue": "^2.0.1", "vue-localstorage": "^0.1.1", "vuex": "^2.2.1" }, "devDependencies": { // 開發(fā)環(huán)境會(huì)用到的東東 "webpack": "^1.13.2", "webpack-dev-middleware": "^1.8.3", "webpack-hot-middleware": "^2.12.2", "webpack-merge": "^0.14.1" } }semantic versioning(語(yǔ)義化版本規(guī)則)
版本格式:主版本號(hào).次版本號(hào).修訂號(hào), 例如 1.2.3
版本號(hào)遞增規(guī)則如下:
主版本號(hào):當(dāng)你做了不兼容的 API 修改; 1.2.3 ---> 2.0.0
次版本號(hào):當(dāng)你做了向下兼容的功能性新增; 1.2.3 ---> 1.3.0
修訂號(hào):當(dāng)你做了向下兼容的問(wèn)題修正; 1.2.3 ---> 1.2.4
在package.json定義版本規(guī)則的時(shí)候,可以這么做:
如果只打算接受補(bǔ)丁版本的更新(也就是最后一位的改變),就可以這么寫:
1.0
1.0.x
~1.0.4
如果接受小版本的更新(第二位的改變),就可以這么寫:
1
1.x
^1.0.4
如果可以接受大版本的更新(自然接受小版本和補(bǔ)丁版本的改變),就可以這么寫:
*
x
在使用npm install --save || npm install --save-dev 安裝的時(shí)候,寫入pakcage.json中的依賴,默認(rèn)接受小版本的更新,即在版本號(hào)前添加 "^"。
NPM document
Node 模塊Node中的模塊分為兩類:
核心模塊(Node中內(nèi)嵌的,比如fs、http等)
文件模塊(開發(fā)者自己編寫的,NPM上的模塊都屬于開發(fā)者自定義的模塊)
文件模塊是在運(yùn)行的時(shí)候,動(dòng)態(tài)加載。需要進(jìn)行路徑分析,文件定位 和 編譯執(zhí)行。
Node加載模塊時(shí),優(yōu)先從緩存中加載,如果緩存中不存在該模塊,才會(huì)按照上述的三個(gè)步驟進(jìn)行模塊加載。
模塊標(biāo)識(shí)符在Node中,主要有以下幾類:
核心模塊,比如fs, http等
以. 或 ..開頭的相對(duì)路徑文件模塊
以/ 開頭的絕對(duì)路徑文件模塊
非路徑形式的文件模塊;
這幾類模塊的加載速度是依次降低的。
module.js
同瀏覽器中的window一樣,在Node中的全局變量都掛在global下。
先說(shuō)一下,常用到一些變量:
__dirname: 當(dāng)前模塊所在目錄
__filename: 當(dāng)前模塊文件名稱
require: 引入其它模塊
module:
exports
上面5個(gè)變量,貌似全局變量,但不是全局變量。他們都是模塊系統(tǒng)下的東西。
question: 它們不在全局變量下,那它們?yōu)楹慰梢栽谀K中直接調(diào)用?
Node引入模塊在Node中,引入模塊分為三個(gè)步驟:
路徑分析
文件定位
編譯執(zhí)行
模塊編譯編譯和執(zhí)行是引入文件模塊的最后一個(gè)階段。
.js文件 : Node 會(huì)對(duì)js源碼進(jìn)行一個(gè)首尾的封裝。返回一個(gè)function,并將當(dāng)前的環(huán)境的exports,require,module,__dirname,__filename作為形參傳遞給這個(gè)function。
包裝后的代碼:
(function(exports, require, module, __filename, __dirname){ // js文件中的源碼 })
這就是為什么 它們不在 全局變量下,卻可以在模塊當(dāng)中使用的原因。
.node文件: 對(duì)于.node文件, 實(shí)際上并不需要編譯過(guò)程。因?yàn)?b>.node文件本身就是C/C++編譯后的文件,它只有加載和執(zhí)行過(guò)程。
.json文件: Node 會(huì)讀取json文件內(nèi)容,并將它賦予exports對(duì)象,直接傳遞給第三方調(diào)用。
在NPM中的模塊,基本屬于Node中文件模塊里的Javascript模塊。
require的規(guī)則Node的模塊系統(tǒng)參照CommonJS規(guī)范實(shí)現(xiàn)。
如果參數(shù)字符串不以./或/或../開頭,說(shuō)明要加載的不是一個(gè)文件,而是一個(gè)默認(rèn)提供的核心模塊。
此時(shí)則先在node平臺(tái)所提供的核心模塊當(dāng)中找;
然后再尋找NPM模塊(即第三方模塊包,或自己寫的模塊包)
在尋找NPM模塊包時(shí),會(huì)從當(dāng)前目錄出發(fā),向上搜索各級(jí)當(dāng)中的node_modules文件夾當(dāng)中的文件,但若有兩個(gè)同名文件,則遵循就近原則。(module.paths是一個(gè)模塊路徑數(shù)組。)
如果require當(dāng)中的參數(shù)字符串以/開頭:則表示從系統(tǒng)根目錄開始尋找該模塊文件。
如果require當(dāng)中的參數(shù)字符串以./(從當(dāng)前目錄出發(fā))或../(從上一級(jí)目錄出發(fā))開頭:表示按照相對(duì)路徑,從當(dāng)前文件所在的文件夾開始尋找要載入的模塊文件。
按js文件來(lái)執(zhí)行(先找對(duì)應(yīng)路徑當(dāng)中的module.js文件來(lái)加載)
按json文件來(lái)解析(若上面的js文件找不到時(shí),則找對(duì)應(yīng)路徑當(dāng)中的module.json文件來(lái)加載)
按照預(yù)編譯好的c++模塊來(lái)執(zhí)行(尋找對(duì)應(yīng)路徑當(dāng)中的module.node文件來(lái)加載)
若參數(shù)字符串為一個(gè)目錄(文件夾)的路徑,則自動(dòng)先查找該文件夾下的package.json文件,然后再再加載該文件當(dāng)中main字段所指定的入口文件。(若package.json文件當(dāng)中沒(méi)有main字段,或者根本沒(méi)有package.json文件,則再默認(rèn)查找該文件夾下的index.js文件作為模塊來(lái)載入。)
processprocess 對(duì)象是一個(gè)全局變量,它提供當(dāng)前 Node.js 進(jìn)程的有關(guān)信息,以及控制當(dāng)前 Node.js 進(jìn)程。
process.argv: 包含命令行參數(shù)的數(shù)組。第一個(gè)元素會(huì)是"node",第二個(gè)元素將是.js文件的名稱,接下來(lái)的參數(shù)依次是命令行參數(shù)
process.execArgv: 啟動(dòng)進(jìn)程所需的 node 命令行參數(shù)。這些參數(shù)不會(huì)在 process.argv 里出現(xiàn),并且不包含 node 執(zhí)行文件的名字,或者任何在名字之后的參數(shù)。這些用來(lái)生成子進(jìn)程,使之擁有和父進(jìn)程有相同的參數(shù)
process.env: 獲取當(dāng)前系統(tǒng)環(huán)境信息的對(duì)象,輸出內(nèi)容是環(huán)境變量等內(nèi)容,這個(gè)對(duì)象可以修改
nextTick(callback): 將callback放到事件輪詢隊(duì)列首位,下一次事件輪詢開始時(shí),先執(zhí)行callback
process.abort:結(jié)束當(dāng)前進(jìn)程
process.kill(pid):結(jié)束一個(gè)進(jìn)程
process.js
console.log(process.argv); console.log(process.execArgv);
node process.js # [ "/usr/local/bin/node", "/root/node-demo/process.js" ] # [] node process.js abc 234 cvb=cvb # [ "/usr/local/bin/node", # "/root/node-demo/process.js", # "abc", # "234", # "cvb=cvb" ] # [] node --harmony --use-openssl-ca process.js abc 234 cvb=cvb # [ "/usr/local/bin/node", # "/root/node-demo/process.js", # "abc", # "234", # "cvb=cvb" ] # [ "--harmony", "--use-openssl-ca" ]
Node"Process document
fsfile.js
Node"FileSystem document
questions require("../fs/file.js")這里是異步還是同步?
deno,下一代Node?package.json
node_modules
gyp
等等............
Node之父JS大會(huì)介紹deno時(shí)的PPT(2018)
Node之父JS大會(huì)介紹Node時(shí)的PPT(2009)
Nodejs的運(yùn)行原理-科普篇
視頻:callstack 和異步 基本原理
Awesome Micro npm Packages
libuv 官網(wǎng)
[深入淺出Node.js]()
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/98694.html
摘要:類鏈表容器也是通過(guò)對(duì)比源碼進(jìn)行對(duì)比學(xué)習(xí)。增加一個(gè)結(jié)點(diǎn)不帶,直接尾插法當(dāng)鏈表里沒(méi)有一個(gè)元素時(shí),頭尾都是該結(jié)點(diǎn),并且該結(jié)點(diǎn)的前后都是空的。尾結(jié)點(diǎn)是該結(jié)點(diǎn)的前驅(qū)結(jié)點(diǎn),該結(jié)點(diǎn)是尾節(jié)點(diǎn)的后繼結(jié)點(diǎn),更新尾節(jié)點(diǎn)。 LinkedList類 鏈表容器也是通過(guò)對(duì)比jdk源碼進(jìn)行對(duì)比學(xué)習(xí)。 1.定義結(jié)點(diǎn)類型 class Node{ E item; Node next; Node prev; Node(No...
摘要:官方文檔官方文檔,官方文檔永遠(yuǎn)是學(xué)習(xí)資料的第一步起步扎實(shí)的基本功。學(xué)習(xí)的新特性,理解,建議可以看看阮一峰的教程。的學(xué)習(xí)曲線會(huì)比較長(zhǎng),需要了解到的常用命令,以及和的模塊規(guī)范,的也很多,其實(shí)更多的是屬于一項(xiàng)后端語(yǔ)言。 學(xué)習(xí)Vue2.0的建議順序 注:本文是看過(guò)其他關(guān)于vue文章之后的想法,歡迎轉(zhuǎn)載,請(qǐng)注明出處。 Vue官方文檔:Vue2.0官方文檔,官方文檔永遠(yuǎn)是學(xué)習(xí)資料的第一步 起步...
摘要:學(xué)習(xí)手動(dòng)寫一個(gè)簡(jiǎn)單的進(jìn)行理解結(jié)點(diǎn)的定義的基礎(chǔ)時(shí)一個(gè)數(shù)組,數(shù)組里每個(gè)元素是一個(gè),他必須包括值,鍵值,,下一個(gè)結(jié)點(diǎn),同一個(gè)值的結(jié)點(diǎn)用一條鏈栓起來(lái)。第一個(gè)結(jié)點(diǎn)的特殊操作第一個(gè)對(duì)上了修改一個(gè)元素查找一個(gè)元素 HashMap學(xué)習(xí)--手動(dòng)寫一個(gè)簡(jiǎn)單的HashMap進(jìn)行理解 1.結(jié)點(diǎn)Node的定義 public class Node { public int hash; public...
摘要:之前寫過(guò)一篇天學(xué)通前端開發(fā),內(nèi)容主要講的就是前端學(xué)習(xí)路徑,今天再來(lái)寫一篇零基礎(chǔ)的學(xué)習(xí)路徑,希望能幫編程零基礎(chǔ)的前端愛(ài)好者指明方向。十框架三選一,零基礎(chǔ)的初學(xué)者強(qiáng)烈推薦,如果是后臺(tái)轉(zhuǎn)前端推薦,如果技術(shù)型前端,推薦。 之前寫過(guò)一篇26天學(xué)通前端開發(fā),內(nèi)容主要講的就是前端學(xué)習(xí)路徑,今天再來(lái)寫一篇零基礎(chǔ)的JavaScript學(xué)習(xí)路徑,希望能幫編程零基礎(chǔ)的前端愛(ài)好者指明方向。 一、開發(fā)環(huán)境和Ja...
摘要:由于這種特性,某一個(gè)任務(wù)的后續(xù)操作,往往采用回調(diào)函數(shù)的形式進(jìn)行定義。另外,回調(diào)函數(shù)本身的第一個(gè)參數(shù),約定為上一步傳入的錯(cuò)誤對(duì)象。這種寫法有一個(gè)很大的好處,就是說(shuō)只要判斷回調(diào)函數(shù)的第一個(gè)參數(shù),就知道有沒(méi)有出錯(cuò),如果不是,就肯定出錯(cuò)了。 REPL環(huán)境 在命令行鍵入node命令,后面沒(méi)有文件名,就進(jìn)入一個(gè)Node.js的REPL環(huán)境(Read–eval–print loop,讀取-求值-輸出...
摘要:謹(jǐn)記,請(qǐng)勿犯這樣的錯(cuò)誤。由于在之前的教程中,積累了堅(jiān)實(shí)的基礎(chǔ)。其實(shí),這是有緣由的其復(fù)雜度在早期的學(xué)習(xí)過(guò)程中,將會(huì)帶來(lái)災(zāi)難性的影響。該如何應(yīng)對(duì)對(duì)于來(lái)說(shuō),雖然有大量的學(xué)習(xí)計(jì)劃需要采取,且有大量的東西需要學(xué)習(xí)。 前言倘若你正在建造一間房子,那么為了能快點(diǎn)完成,你是否會(huì)跳過(guò)建造過(guò)程中的部分步驟?如在具體建設(shè)前先鋪設(shè)好部分石頭?或直接在一塊裸露的土地上先建立起墻面? 又假如你是在堆砌一個(gè)結(jié)婚蛋糕...
閱讀 3979·2021-11-24 09:38
閱讀 1243·2021-10-19 11:42
閱讀 1840·2021-10-14 09:42
閱讀 2166·2019-08-30 15:44
閱讀 555·2019-08-30 14:04
閱讀 2901·2019-08-30 13:13
閱讀 1963·2019-08-30 12:51
閱讀 972·2019-08-30 11:22