新手必須知的Node.js 4個(gè)JavaScript基本概念
Node.js是建立在Chrome強(qiáng)勁的V8 JavaScript引擎上的服務(wù)器端框架。雖然最初是用C++編寫的,但是應(yīng)用程序通過JavaScript運(yùn)行。
下面這4個(gè)基本概念是你想要掌握node.js所必需的。我會(huì)盡可能長話短說向大家介紹它們。
1.非阻塞或異步I/O
由于Node.js是一種服務(wù)器端框架,所以它的一個(gè)主要工作就是處理瀏覽器請求。在傳統(tǒng)的I/O系統(tǒng)中,當(dāng)前請求只有當(dāng)先前請求的響應(yīng)(HTML頁面)已到達(dá)才會(huì)發(fā)出。這就是為什么它被稱為阻塞I/O。服務(wù)器阻塞其他請求是為了處理當(dāng)前的請求,而這會(huì)導(dǎo)致瀏覽器的等待。
Node.js不遵循I/O的這個(gè)原則。如果一個(gè)請求需要花費(fèi)較長時(shí)間,那么Node.js會(huì)發(fā)送請求到事件循環(huán)(event loop)中,并繼續(xù)在調(diào)用棧(call stack)中處理下一個(gè)請求。一旦未決請求完成處理,它就會(huì)告訴Node.js,并將響應(yīng)渲染在瀏覽器上。
用一個(gè)虛擬的例子來理解這一點(diǎn):
阻塞I / O
// take order for table 1 and wait... var order1 = orderBlocking(['Coke', 'Iced Tea']); // once order is ready, take order back to table. serveOrder(order1); // once order is delivered, move on to another table. // take order for table 2 and wait... var order2 = orderBlocking(['Coke', 'Water']); // once order is ready, take order back to table. serveOrder(order2); // once order is delivered, move on to another table. // take order for table 3 and wait... var order3 = orderBlocking(['Iced Tea', 'Water']); // once order is ready, take order back to table. serveOrder(order3); // once order is delivered, move on to another table.
在這個(gè)餐廳例子中,服務(wù)員給出菜單,等待訂單完成,然后再回到餐桌根據(jù)菜單上菜。在當(dāng)前客戶點(diǎn)菜時(shí),服務(wù)員就在旁邊等待,不接受其他客戶的菜單。
非阻塞I / O
// take order for table 1 and move on... orderNonBlocking(['Coke', 'Iced Tea'], function(drinks){ return serveOrder(drinks); }); // take order for table 2 and move on... orderNonBlocking(['Beer', 'Whiskey'], function(drinks){ return serveOrder(drinks); }); // take order for table 3 and move on... orderNonBlocking(['Hamburger', 'Pizza'], function(food){ return serveOrder(food); });
在這個(gè)例子中,服務(wù)員獲得菜單,并告知廚師,然后返回取另一份菜單。在完成第一個(gè)菜單進(jìn)程中,他既按照順序給當(dāng)前顧客上菜,也接受來自其他客戶的點(diǎn)單。服務(wù)員不會(huì)因?yàn)樽枞麃碜杂谄渌蛻舻狞c(diǎn)菜而浪費(fèi)時(shí)間。
2.原型
原型是JavaScript的一個(gè)復(fù)雜概念。不過因?yàn)樵贜ode.js中你要多次用到原型,所以每個(gè)JavaScript開發(fā)人員都必須了解這個(gè)概念。
在實(shí)現(xiàn)經(jīng)典繼承的語言中,例如Java,或C ++,對于以代碼重用為目的的語言,你首先必須寫一個(gè)類,然后從該類創(chuàng)建對象或擴(kuò)展該類。但是,在JavaScript中不存在類的概念。首先在JavaScript中創(chuàng)建一個(gè)對象,然后從這個(gè)對象中增加自己的對象,或創(chuàng)建新的對象。這就是所謂的原型傳承和通過原型的實(shí)現(xiàn)。
每個(gè)JavaScript對象被鏈接到一個(gè)來自于它可以繼承屬性的原型對象。原型類似其他OO語言中的類,但不同的是,它們本身也是對象。每一個(gè)對象都鏈接到Object.prototype,而Object.prototype自帶JavaScript預(yù)定義。
如果你通過obj.propName或 obj['propName'] 查找屬性,而對象并不具有可通過 obj.hasOwnProperty(‘propName')被檢查的屬性,那么JavaScript的運(yùn)行時(shí)會(huì)在其原型對象中查找屬性。如果原型對象也沒有這樣的屬性,那么依次檢查它的原型,直到找到匹配,或者到達(dá)Object.prototype。如果該屬性不存在原型鏈,那么它會(huì)導(dǎo)致一個(gè)未定義的值。
通過下面的示例代碼來理解這個(gè)概念:
if (typeof Object.create !== 'function') { Object.create = function (o) { var F = function () {}; F.prototype = o; return new F(); }; var otherPerson = Object.create(person);
當(dāng)你創(chuàng)建一個(gè)新對象的時(shí)候,你必須選擇一個(gè)應(yīng)該是它的原型的對象。這里,我們添加了一個(gè)方法到Object function。該方法創(chuàng)建了一個(gè)使用另一個(gè)對象作為其原型的新對象,而原型作為參數(shù)傳遞給它。
當(dāng)我們改變新對象的時(shí)候,它的原型不受影響。但是,當(dāng)我們進(jìn)行改變原型對象的時(shí)候,這些變化在所有基于該原型的對象上可見。
原型是一個(gè)復(fù)雜的概念。我將在另一篇文章中詳細(xì)說明。
3.模塊
如果你曾經(jīng)接觸過Java中的包,那么Node.js中的模塊也沒有什么不同。如果沒有,那么也不用擔(dān)心。模塊是包含特定目的代碼的簡單的JavaScript文件。模塊模式用來使你的代碼易于導(dǎo)航和使用。要使用模塊屬性,你需要在JavaScript文件中需求它,很像在Java類中導(dǎo)入包。
node.js中有兩種類型的模塊。
核心模塊——這些模塊是用Node.js庫預(yù)編譯過的。核心模塊的目的是提供開發(fā)者經(jīng)常發(fā)生和重復(fù)的代碼段,這些代碼段如果不可用的話,會(huì)導(dǎo)致開發(fā)者陷入不得不一次又一次地寫相同代碼的處境。一些常見的核心模塊是HTTP,URL,EVENTS,F(xiàn)ILE SYSTEM,等等。
用戶定義模塊——用戶定義模塊是開發(fā)人員在應(yīng)用程序內(nèi)創(chuàng)建用于特定目的的模塊。當(dāng)核心模塊不能滿足期望功能的時(shí)候就需要用戶定義模塊。
模塊通過require函數(shù)提取。如果它是一個(gè)核心模塊,那么參數(shù)僅僅是模塊的名稱。如果它是一個(gè)用戶自定義模塊,那么參數(shù)就是該模塊在文件系統(tǒng)中的路徑。例如:
// extract a core module like this var http = require('http); // extract a user defined module like this var something = require('./folder1/folder2/folder3/something.js');
4.回調(diào)函數(shù)
在JavaScript中,函數(shù)被認(rèn)為是第一類對象。這意味著你可以對這些函數(shù)做所有可對常規(guī)對象做的操作。你可以賦值函數(shù)給變量,作為參數(shù)傳遞函數(shù)給方法,作為對象屬性聲明函數(shù),甚至從函數(shù)返回函數(shù)。
回調(diào)函數(shù)是JavaScript中的匿名函數(shù),它可以作為參數(shù)傳遞給其他函數(shù),要么被執(zhí)行或返回自函數(shù)稍后執(zhí)行。這是回調(diào)函數(shù)——這個(gè)使用最廣的函數(shù)編程范式的基礎(chǔ)。
當(dāng)我們將回調(diào)函數(shù)作為參數(shù)傳遞給另一個(gè)函數(shù)的時(shí)候,我們只能傳遞函數(shù)定義……換言之就是,我們不知道這個(gè)回調(diào)函數(shù)什么時(shí)候會(huì)執(zhí)行。這完全取決于調(diào)用函數(shù)的機(jī)制。它會(huì)在以后的某個(gè)時(shí)間點(diǎn)“回調(diào)”,因此而得名。這也是非阻塞或Node.js異步行為的唯一基礎(chǔ),如下例所示。
setTimeout(function() { console.log("world"); }, 2000) console.log("hello");
這是回調(diào)函數(shù)最簡單的例子之一。我們將一個(gè)匿名函數(shù)作為一個(gè)參數(shù)傳遞,這個(gè)參數(shù)只需在控制臺(tái)上記錄一些輸出到setTimeout函數(shù)。它是唯一的函數(shù)定義,但是不知道何時(shí)執(zhí)行。這需要經(jīng)過2秒后,通過第二個(gè)參數(shù),調(diào)用setTimeout函數(shù)來決定。
首先,第二個(gè)日志語句記錄輸出到控制臺(tái),然后,2秒鐘后,回調(diào)函數(shù)中的日志語句記錄輸出。
// output hello world
以上4條JavaScript概念是Node.js新手必須知的個(gè)最重要概念,越是基礎(chǔ)的東西越是重要,大家一家要牢記
相關(guān)文章
從零開始學(xué)習(xí)Node.js系列教程二:文本提交與顯示方法
這篇文章主要介紹了Node.js文本提交與顯示方法,結(jié)合實(shí)例形式分析了nodejs基于http的文本提交、傳輸與顯示相關(guān)操作技巧,需要的朋友可以參考下2017-04-04node.js降低版本的方式詳解(解決sass和node.js沖突問題)
這篇文章主要介紹了node.js降低版本的方式(解決sass和node.js沖突),本文是因?yàn)閟ass版本和node版本不匹配(可以找一下對應(yīng)的版本),本文給大家詳細(xì)講解,需要的朋友可以參考下2023-02-02Node.js前后端交互實(shí)現(xiàn)用戶登陸的實(shí)踐
本文主要介紹了Node.js前后端交互實(shí)現(xiàn)用戶登陸的實(shí)踐,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-12-12Express下采用bcryptjs進(jìn)行密碼加密的方法
本篇文章主要介紹了Express下采用bcryptjs進(jìn)行密碼加密的方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-02-02nodejs實(shí)現(xiàn)發(fā)送郵箱驗(yàn)證碼功能
這篇文章主要為大家詳細(xì)介紹了nodejs實(shí)現(xiàn)發(fā)送郵箱驗(yàn)證碼功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-04-04基于node搭建服務(wù)器,寫接口,調(diào)接口,跨域的實(shí)例
今天小編就為大家分享一篇基于node搭建服務(wù)器,寫接口,調(diào)接口,跨域的實(shí)例,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-05-05Nodejs回調(diào)加超時(shí)限制兩種實(shí)現(xiàn)方法
這篇文章主要介紹了Nodejs回調(diào)加超時(shí)限制兩種實(shí)現(xiàn)方法的相關(guān)資料,需要的朋友可以參考下2017-06-06