最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Nodejs學(xué)習(xí)筆記之入門篇

 更新時(shí)間:2015年04月16日 10:59:25   投稿:hebedich  
本系列教程致力于教會(huì)你如何用Node.js來(lái)開發(fā)應(yīng)用,過(guò)程中會(huì)傳授你所有所需的“高級(jí)”JavaScript知識(shí)。絕不是一篇“Hello World”的教程。

分享第一篇,關(guān)于 NodeJS —— Javascript 的常用知識(shí)以及如何從 Javascript 開發(fā)者過(guò)渡到 NodeJS 開發(fā)者(不會(huì)介紹具體的框架)。在讀本文前,希望你對(duì) javascript 有一些初步的認(rèn)識(shí)。

Javascript 是一門原型模型的解釋型語(yǔ)言。解釋型將在后面的 NodeJS 里面討論,原型鏈?zhǔn)?ES6 之前的 Javascript 的面向?qū)ο蟮膶?shí)現(xiàn)方式之一,在 ES6 中支持的 class 增加了一種新的實(shí)現(xiàn)方式。在 Javascript 里面所有東西都是對(duì)象,包括 “類”。接觸過(guò) ruby/python 的元編程的可能會(huì)覺得這個(gè)很熟悉,Javascript 也很容易是實(shí)現(xiàn)出動(dòng)態(tài)的生成類的方法。

1. 基于原型鏈實(shí)現(xiàn)的簡(jiǎn)單的“類”

var Person = function(name){
 this.name = name;
};

Person.staticSay = function(name){
 console.log('Hello ' + name);
};

Person.prototype.sayHi = function(){
 Person.staticSay(this.name);
}

提一些常見的規(guī)范,例如 Javascript 中所有的方法都是駝峰命名,優(yōu)先使用單引號(hào),兩個(gè)空格等等,更多的規(guī)范可以參考 https://github.com/airbnb/javascript。

代碼中的staticSay為靜態(tài)方法,即只能通過(guò) Person.staticSay來(lái)調(diào)用。 當(dāng)上面的 Person 生成實(shí)例的時(shí)候,例如 var vincent = new Person('vincent');的時(shí)候,vincent會(huì)自動(dòng)繼承 Person.prototype 的所有方法(代碼中的 this 指代的是當(dāng)前上下文,即上文中的 vincent)。

同時(shí)也可以動(dòng)態(tài)的為對(duì)象 vincent 添加方法,例如如下代碼:

var vincent = new Person('vincent')
vincent.tellName = function(){
 console.log('Hi, i\'m am' + this.name)
};

然后當(dāng)你需要模擬繼承的時(shí)候,就需要在 prototype 上下功夫。例如下面使用 Worker.prototype = new Person() 來(lái)實(shí)現(xiàn),new Person() 返回的實(shí)例對(duì)象帶著的所有方法、屬性都被賦給了 prototype,變相模擬了繼承。這種方式最終一層層的往上找 prototype 里面的內(nèi)容(因?yàn)槊總€(gè)實(shí)例具有的方法都在 prototype 里面,往上直到 Object)。當(dāng)然也可以通過(guò)遍歷來(lái)進(jìn)行對(duì) prototype 賦值來(lái)模擬繼承。

2. 上下文切換

上下文最直觀的表現(xiàn)就是代碼塊中的 this,通常在面向?qū)ο蟮木幊讨杏玫?,?lái)指代當(dāng)前“類”生成的對(duì)應(yīng)實(shí)例,與其他語(yǔ)言的 self一致。

繼續(xù)用上文中的例子,上文中已經(jīng)實(shí)現(xiàn)了一個(gè) Person.prototype.sayHi方法,現(xiàn)在我有一個(gè)新的對(duì)象,代碼如下:

var Cat = function(name){
 this.name = name;
}

var c = new Cat('tomcat');

如果某天突然異想天開希望這只貓像人一樣介紹他自己怎么辦,他自己沒有 sayHi 這個(gè)方法。但是可以通過(guò) console.log(Person.prototype.sayHi)是可以拿到人類的 sayHi 方法的,怎么讓貓也可以使用呢?

Javascript 有兩個(gè)方法,call 和 apply,他們的區(qū)別就是參數(shù)不同(自行谷歌),作用是用來(lái)切換上下文。簡(jiǎn)單說(shuō)就是可以把 Person.prototype.sayHi這個(gè)函數(shù)中的 this 變成其他對(duì)象。使用方式: Person.prototype.sayHi.call(c)。

這個(gè)實(shí)用嘛?例如如下場(chǎng)景:

var doSomething = function(){
 var persons = arguments;
};

上面的函數(shù)中,通過(guò)關(guān)鍵字 arguments獲取所有的參數(shù)來(lái)支持不定數(shù)量的參數(shù)?,F(xiàn)在我們希望對(duì) persons用一些原屬于 Array 類型的方法,如何實(shí)現(xiàn)呢?這里就可以用上下文切換來(lái)實(shí)現(xiàn):

var doSomething = function(){
 var persons = arguments;
 // 使用 Array 的 slice 方法,將 arguments 對(duì)象轉(zhuǎn)變?yōu)?Array 實(shí)例
 var persons_arr = Array.prototype.slice.call(arguments);
};

3. 閉包

先來(lái)段常見的代碼

for (var i = 0; i < 3; i ++){
 setTimeout(function(){
  console.log(i);
 }, i)
}

這個(gè)會(huì)輸出什么結(jié)果呢?依次輸出 0 1 2 ?實(shí)際情況是,當(dāng) setTimeout第一次執(zhí)行回調(diào)的時(shí)候,for 循環(huán)已經(jīng)結(jié)束了,也就是說(shuō)此時(shí)的 i 已經(jīng)是 3 了,導(dǎo)致最終的輸出結(jié)果是 3 3 3。

當(dāng)你需要保護(hù)某一個(gè)變量,使得他不被外圍的代碼所影響的時(shí)候,你可能就需要考慮下閉包 —— 一個(gè)封閉的作用域的代碼塊。

for (var i = 0; i < 3; i ++){
 +function(i){
  setTimeout(function(){
   console.log(i);
  }, i)
 }(i)
}

咦, +是干嘛的,有沒有其他方式實(shí)現(xiàn),請(qǐng)自行谷歌。閉包內(nèi)的 i 的作用域是一個(gè)封閉的作用域,所以最終 閉包內(nèi)的 i 一直沒有被外面的執(zhí)行改變,所以可以成功的輸出 0 1 2。

簡(jiǎn)單的介紹了 javascript 部分特性,關(guān)鍵字 原型鏈、call 和 apply、arguments 關(guān)鍵字,更多的建議可以看看例如權(quán)威指南這樣的書,或者快速了解下基本的類型以及每個(gè)類型有的方法。有一些比較神奇的代碼,例如獲得當(dāng)前的代碼的字符串,然后進(jìn)行處理得到自己想要的內(nèi)容,使用 getter 和 setter 在用戶對(duì)對(duì)象屬性獲取或者賦值的時(shí)候做一些特殊的操作等等。

4. NodeJS 和 Javascript 的開發(fā)區(qū)別

這塊主要介紹 require 加載的基礎(chǔ)知識(shí),首先先介紹一些代碼:

// a.js
module.exports = {
 name: "a",
 doSomething: function(){
  return "something";
 }
}

// b.js
var a = require('./a')
global.a_name = a.name;

// c.js
require('./b');
console.log(a_name) // 執(zhí)行后打印 a 

當(dāng)我們執(zhí)行 node c.js的時(shí)候發(fā)生了什么?

require是 nodes 關(guān)鍵字,雖然 NodeJS 是以異步著稱,但是他的 require都是阻塞的。否則就會(huì)出現(xiàn)還沒有載入其他模塊,已經(jīng)開始執(zhí)行下面的代碼的情況。

require.resolve()方法是用來(lái)找出你所引用的文件的實(shí)際路徑,找出后 Nodejs 會(huì)在 require.cache里面尋找是否有緩存,沒有的話則會(huì)讀取文件然后解析,所以通常情況下,一個(gè) js 文件里面的執(zhí)行的代碼只會(huì)在第一次被 require 的時(shí)候被執(zhí)行。(tip. require.cache 如果有需要的話是可以手動(dòng)刪除一些東西的,然后可以某種程度上可以執(zhí)行多次)

當(dāng) b.js 開始執(zhí)行的時(shí)候,他需要先載入 a.js,module.exports告訴 Nodejs 這個(gè)文件對(duì)外暴露寫什么,例如 a.js 暴露的是一個(gè)對(duì)象,包含 name 屬性和 doSomething 方法。然后 b.js 中的 a 變量其實(shí)就是這個(gè)對(duì)象。

執(zhí)行完獲取 a.js 后,繼續(xù)回到 b.js ,global.a_name 相當(dāng)于聲明了一個(gè)全局變量,這個(gè)和前端中的 window.a_name = a.name 效果類似。

最終過(guò)程完成,c.js 執(zhí)行輸出值。

5. 異步的底層原理

NodeJS 很容易給人一種使用上的錯(cuò)覺,就是寫了很久都可能不知道底層的異步是怎么實(shí)現(xiàn)的。(下面的理解主要來(lái)自于對(duì) python3.4 中的 asyncio 的理解,如有錯(cuò)誤歡迎指出)。

NodeJS 底層的 libev 分別在 Window 下使用 IOCP 和 *nix 下使用基于 AIO 的 libeio 來(lái)實(shí)現(xiàn)異步。通過(guò)系統(tǒng)層面的技術(shù),最后達(dá)到一個(gè)目的,就是應(yīng)用程序發(fā)起一個(gè)異步請(qǐng)求,最終在系統(tǒng)執(zhí)行完后,系統(tǒng)通知應(yīng)用程序處理完成。在這個(gè)過(guò)程中,應(yīng)用程序可以將之前的處理掛起/推入線程池中等待執(zhí)行,而應(yīng)用程序在此期間可以執(zhí)行其他任務(wù)。

整個(gè)的運(yùn)行通過(guò)系統(tǒng)層面的事件循環(huán)來(lái)進(jìn)行運(yùn)作。例如 Python 提供了類似于 run_until 以及 run_forever 的這樣的方法,保證在異步執(zhí)行之前程序不會(huì)結(jié)束運(yùn)行。將整個(gè)異步想象成一個(gè)一直在運(yùn)作的車間,車間里面的機(jī)器負(fù)責(zé)查看包裹并蓋章這樣的操作,工人拿到了一個(gè)包裹,然后貼上相應(yīng)的標(biāo)簽后放進(jìn)去,等車間處理完后再交還給工人,工人根據(jù)包裹上他之前貼上的標(biāo)簽和被車間貼上的標(biāo)簽,進(jìn)行下一步的處理。工人無(wú)需等待包裹檢查完畢才能進(jìn)行下一個(gè),他只需要接受簡(jiǎn)單處理,然后放入車間進(jìn)行檢查。然后等某個(gè)時(shí)間車間返回給他某個(gè)包裹,他再去進(jìn)行下一步的操作。

目前主要還是只介紹了一些語(yǔ)言層面的知識(shí),但是只有這些距離開發(fā)一個(gè)完整的 web 還有一些距離,將在后面繼續(xù)介紹。包括 Redis,Nginx,測(cè)試驅(qū)動(dòng)等等。

以上所述就是本文的全部?jī)?nèi)容了,希望大家能夠喜歡。

相關(guān)文章

  • Node如何實(shí)現(xiàn)在瀏覽器預(yù)覽項(xiàng)目的所有圖片詳解

    Node如何實(shí)現(xiàn)在瀏覽器預(yù)覽項(xiàng)目的所有圖片詳解

    最近項(xiàng)目遇到了個(gè)需求,需要將存放圖片進(jìn)行預(yù)覽,所以這篇文章主要給大家介紹了關(guān)于Node如何實(shí)現(xiàn)在瀏覽器預(yù)覽項(xiàng)目的所有圖片的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-01-01
  • Nodejs調(diào)用Dll模塊的方法

    Nodejs調(diào)用Dll模塊的方法

    這篇文章主要介紹了Nodejs調(diào)用Dll模塊的方法,在文中給大家提到了nodejs通過(guò)ffi調(diào)用dll模塊的代碼,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2018-09-09
  • node靜態(tài)服務(wù)器實(shí)現(xiàn)靜態(tài)讀取文件或文件夾

    node靜態(tài)服務(wù)器實(shí)現(xiàn)靜態(tài)讀取文件或文件夾

    這篇文章主要介紹了node靜態(tài)服務(wù)器實(shí)現(xiàn)靜態(tài)讀取文件或文件夾,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-12-12
  • nodejs 遞歸拷貝、讀取目錄下所有文件和目錄

    nodejs 遞歸拷貝、讀取目錄下所有文件和目錄

    這篇文章主要介紹了nodejs 遞歸拷貝、讀取目錄下所有文件和目錄,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2019-07-07
  • 詳解nodeJS之二進(jìn)制buffer對(duì)象

    詳解nodeJS之二進(jìn)制buffer對(duì)象

    本篇文章主要介紹了nodeJS之二進(jìn)制buffer對(duì)象,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-06-06
  • Node.js檢測(cè)端口(port)是否被占用的簡(jiǎn)單示例

    Node.js檢測(cè)端口(port)是否被占用的簡(jiǎn)單示例

    大家有沒有遇到過(guò)在開啟本地服務(wù)時(shí),有這么一種情況:當(dāng)前端口已經(jīng)被另一個(gè)項(xiàng)目使用了,導(dǎo)致服務(wù)開啟失敗。那么接下來(lái),我們通過(guò)簡(jiǎn)簡(jiǎn)單單的示例代碼來(lái)檢測(cè)端口是否已經(jīng)被占用。有需要的朋友們可以參考借鑒。
    2016-09-09
  • 查詢Node.js版本信息的六種方法

    查詢Node.js版本信息的六種方法

    隨著應(yīng)用程序規(guī)模越來(lái)越龐大,Node.js版本的更新也日益頻繁,本文主要介紹了查詢Node.js版本信息的六種方法,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-03-03
  • Node版本切換不成功的問(wèn)題解決

    Node版本切換不成功的問(wèn)題解決

    使用 Node.js 和 npm 安裝 Taro 等工具時(shí),可能會(huì)遇到一些環(huán)境問(wèn)題或配置錯(cuò)誤,本文就來(lái)介紹一下Node版本切換不成功的問(wèn)題解決,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-12-12
  • koa+mongoose實(shí)現(xiàn)簡(jiǎn)單增刪改查接口的示例代碼

    koa+mongoose實(shí)現(xiàn)簡(jiǎn)單增刪改查接口的示例代碼

    這篇文章主要介紹了koa+mongoose實(shí)現(xiàn)簡(jiǎn)單增刪改查接口的示例代碼,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2019-05-05
  • nodeJS實(shí)現(xiàn)路由功能實(shí)例代碼

    nodeJS實(shí)現(xiàn)路由功能實(shí)例代碼

    本篇文章主要介紹了nodeJS實(shí)現(xiàn)路由功能實(shí)例代碼,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-06-06

最新評(píng)論

周至县| 南岸区| 大洼县| 长治市| 滁州市| 怀集县| 玛多县| 榆林市| 仙桃市| 定日县| 祁阳县| 涡阳县| 浑源县| 海晏县| 肥西县| 朝阳区| 遂宁市| 安康市| 武平县| 信阳市| 应用必备| 昌乐县| 南投市| 陆良县| 白河县| 青岛市| 望谟县| 上杭县| 集安市| 淮北市| 乌拉特后旗| 古浪县| 镇远县| 宜阳县| 鄱阳县| 射阳县| 苗栗县| 富平县| 石狮市| 裕民县| 云阳县|