欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Nodejs學(xué)習(xí)筆記之Global Objects全局對(duì)象

 更新時(shí)間:2015年01月13日 10:08:09   投稿:hebedich  
本文是NodeJS學(xué)習(xí)筆記系列文章的第二篇,從這篇開始我們就根據(jù)官方文檔來逐個(gè)學(xué)習(xí)下NodeJS的各個(gè)模塊,首先我們來學(xué)習(xí)下Global

一,開篇分析

在上個(gè)章節(jié)中我們學(xué)習(xí)了NodeJS的基礎(chǔ)理論知識(shí),對(duì)于這些理論知識(shí)來說理解是至關(guān)重要的,在后續(xù)的章節(jié)中,我們會(huì)對(duì)照著官方文檔逐步學(xué)習(xí)里面的各部分模塊,好了該是本文主角登臺(tái)亮相的時(shí)候了,Global

讓我們來看一下官方的定義:

Global Objects全局對(duì)象These objects are available in all modules. Some of these objects aren't actually in the global scope but in the module scope - this will be noted.

這些對(duì)象在所有的模塊中都可用。實(shí)際上有些對(duì)象并不在全局作用域范圍中,但是在它的模塊作用域中------這些會(huì)標(biāo)識(shí)出來的。

In browsers, the top-level scope is the global scope. That means that in browsers if you're in the global scopevar somethingwill define a global variable.

In Node this is different. The top-level scope is not the global scope;var somethinginside a Node module will be local to that module.

全局對(duì)象這個(gè)概念我想大家應(yīng)該不會(huì)感到陌生,在瀏覽器中,最高級(jí)別的作用域是Global Scope ,這意味著如果你在Global Scope中使用 "var" 定義一個(gè)變量,這個(gè)變量將會(huì)被定義成Global Scope。

但是在NodeJS里是不一樣的,最高級(jí)別的Scope不是Global Scope,在一個(gè)Module里用 "var" 定義個(gè)變量,這個(gè)變量只是在這個(gè)Module的Scope里。

在NodeJS中,在一個(gè)模塊中定義的變量,函數(shù)或方法只在該模塊中可用,但可以通過exports對(duì)象的使用將其傳遞到模塊外部。

但是,在Node.js中,仍然存在一個(gè)全局作用域,即可以定義一些不需要通過任何模塊的加載即可使用的變量、函數(shù)或類。

同時(shí),也預(yù)先定義了一些全局方法及全局類Global對(duì)象就是NodeJS中的全局命名空間,任何全局變量,函數(shù)或?qū)ο蠖际窃搶?duì)象的一個(gè)屬性值。

在REPL運(yùn)行環(huán)境中,你可以通過如下語句來觀察Global對(duì)象中的細(xì)節(jié)內(nèi)容,見下圖:

我在下面會(huì)逐一說說掛載在Global對(duì)象上的相關(guān)屬性值對(duì)象。

(1),Process

  process {Object} The process object.See the process object section.

  process {對(duì)象} 這是一個(gè)進(jìn)程對(duì)象。 在后續(xù)的章節(jié)中我會(huì)細(xì)說,但在這里我要先拿出一個(gè)api來說一下。

  process.nextTick(callback)

  On the next loop around the event loop call this callback. This is not a simple alias to setTimeout(fn, 0), it's much more efficient. It typically runs before any other I/O events fire, but there are some      exceptions. See process.maxTickDepth below.

  在事件循環(huán)的下一次循環(huán)中調(diào)用 callback 回調(diào)函數(shù)。這不是 setTimeout(fn, 0) 函數(shù)的一個(gè)簡單別名,因?yàn)樗男矢叨嗔恕?/p>

  該函數(shù)能在任何 I/O 事前之前調(diào)用我們的回調(diào)函數(shù)。如果你想要在對(duì)象創(chuàng)建之后而I/O 操作發(fā)生之前執(zhí)行某些操作,那么這個(gè)函數(shù)對(duì)你而言就十分重要了。

  有很多人對(duì)Node.js里process.nextTick()的用法感到不理解,下面我們就來看一下process.nextTick()到底是什么,該如何使用。

   Node.js是單線程的,除了系統(tǒng)IO之外,在它的事件輪詢過程中,同一時(shí)間只會(huì)處理一個(gè)事件。你可以把事件輪詢想象成一個(gè)大的隊(duì)列,在每個(gè)時(shí)間點(diǎn)上,系統(tǒng)只會(huì)處理一個(gè)事件。

   即使你的電腦有多個(gè)CPU核心,你也無法同時(shí)并行的處理多個(gè)事件。但也就是這種特性使得node.js適合處理I/O型的應(yīng)用,不適合那種CPU運(yùn)算型的應(yīng)用。

   在每個(gè)I/O型的應(yīng)用中,你只需要給每一個(gè)輸入輸出定義一個(gè)回調(diào)函數(shù)即可,他們會(huì)自動(dòng)加入到事件輪詢的處理隊(duì)列里。

  當(dāng)I/O操作完成后,這個(gè)回調(diào)函數(shù)會(huì)被觸發(fā)。然后系統(tǒng)會(huì)繼續(xù)處理其他的請(qǐng)求。

  

  在這種處理模式下,process.nextTick()的意思就是定義出一個(gè)動(dòng)作,并且讓這個(gè)動(dòng)作在下一個(gè)事件輪詢的時(shí)間點(diǎn)上執(zhí)行。我們來看一個(gè)例子。例子中有一個(gè)foo(),你想在下一個(gè)時(shí)間點(diǎn)上調(diào)用他,可以這么做:

復(fù)制代碼 代碼如下:

function foo() {
    console.error('foo');
}
 
process.nextTick(foo);
console.error('bar');

運(yùn)行上面的代碼,你從下面終端打印的信息會(huì)看到,"bar"的輸出在“foo”的前面。這就驗(yàn)證了上面的說法,foo()是在下一個(gè)時(shí)間點(diǎn)運(yùn)行的。

復(fù)制代碼 代碼如下:

bar
foo

  你也可以使用setTimeout()函數(shù)來達(dá)到貌似同樣的執(zhí)行效果:

復(fù)制代碼 代碼如下:

setTimeout(foo, 0);
console.log('bar');

  但在內(nèi)部的處理機(jī)制上,process.nextTick()和setTimeout(fn, 0)是不同的,process.nextTick()不是一個(gè)單純的延時(shí),他有更多的特性。

  更精確的說,process.nextTick()定義的調(diào)用會(huì)創(chuàng)建一個(gè)新的子堆棧。在當(dāng)前的棧里,你可以執(zhí)行任意多的操作。但一旦調(diào)用netxTick,函數(shù)就必須返回到父堆棧。然后事件輪詢機(jī)制又重新等待處理新的事件,如果發(fā)現(xiàn)nextTick的調(diào)用,就會(huì)創(chuàng)建一個(gè)新的棧。

  下面我們來看看,什么情況下使用process.nextTick():

  在多個(gè)事件里交叉執(zhí)行CPU運(yùn)算密集型的任務(wù):

  在下面的例子里有一個(gè)compute(),我們希望這個(gè)函數(shù)盡可能持續(xù)的執(zhí)行,來進(jìn)行一些運(yùn)算密集的任務(wù)。

  但與此同時(shí),我們還希望系統(tǒng)不要被這個(gè)函數(shù)堵塞住,還需要能響應(yīng)處理別的事件。這個(gè)應(yīng)用模式就像一個(gè)單線程的web服務(wù)server。在這里我們就可以使用process.nextTick()來交叉執(zhí)行compute()和正常的事件響應(yīng)。

復(fù)制代碼 代碼如下:

var http = require('http');
function compute() {
    // performs complicated calculations continuously
    // ...
    process.nextTick(compute);
}
http.createServer(function(req, res) {
     res.writeHead(200, {'Content-Type': 'text/plain'});
     res.end('Hello World');
}).listen(5000, '127.0.0.1');
compute();

  在這種模式下,我們不需要遞歸的調(diào)用compute(),我們只需要在事件循環(huán)中使用process.nextTick()定義compute()在下一個(gè)時(shí)間點(diǎn)執(zhí)行即可。

  在這個(gè)過程中,如果有新的http請(qǐng)求進(jìn)來,事件循環(huán)機(jī)制會(huì)先處理新的請(qǐng)求,然后再調(diào)用compute()。

  反之,如果你把compute()放在一個(gè)遞歸調(diào)用里,那系統(tǒng)就會(huì)一直阻塞在compute()里,無法處理新的http請(qǐng)求了。你可以自己試試。

  當(dāng)然,我們無法通過process.nextTick()來獲得多CPU下并行執(zhí)行的真正好處,這只是模擬同一個(gè)應(yīng)用在CPU上分段執(zhí)行而已。

 ?。?),Console

  console {Object} Used to print to stdout and stderr.See the stdio section.

  控制臺(tái) {對(duì)象} 用于打印到標(biāo)準(zhǔn)輸出和錯(cuò)誤輸出。看如下測(cè)試:

  

復(fù)制代碼 代碼如下:

console.log("Hello Bigbear !") ;
for(var i in console){
    console.log(i+"  "+console[i]) ;
}

  會(huì)得到以下輸出結(jié)果: 

復(fù)制代碼 代碼如下:

var log = function () {
  process.stdout.write(format.apply(this, arguments) + '\n');
}
var info = function () {
  process.stdout.write(format.apply(this, arguments) + '\n');
}
var warn = function () {
  writeError(format.apply(this, arguments) + '\n');
}
var error = function () {
  writeError(format.apply(this, arguments) + '\n');
}
var dir = function (object) {
  var util = require('util');
  process.stdout.write(util.inspect(object) + '\n');
}
var time = function (label) {
  times[label] = Date.now();
}
var timeEnd = function (label) {
  var duration = Date.now() - times[label];
  exports.log('undefined: NaNms', label, duration);
}
var trace = function (label) {
  // TODO probably can to do this better with V8's debug object once that is
  // exposed.
  var err = new Error;
  err.name = 'Trace';
  err.message = label || '';
  Error.captureStackTrace(err, arguments.callee);
  console.error(err.stack);
}
var assert = function (expression) {
  if (!expression) {
    var arr = Array.prototype.slice.call(arguments, 1);
    require('assert').ok(false, format.apply(this, arr));
  }
}

  通過這些函數(shù),我們基本上知道NodeJS在全局作用域添加了些什么內(nèi)容,其實(shí)Console對(duì)象上的相關(guān)api只是對(duì)Process對(duì)象上的"stdout.write“進(jìn)行了更高級(jí)的封裝掛在到了全局對(duì)象上。

?。?),exports與module.exports

   在NodeJS中,有兩種作用域,分為全局作用域和模塊作用域  

復(fù)制代碼 代碼如下:

var name = 'var-name';
name = 'name';
global.name='global-name';
this.name = 'module-name';
console.log(global.name);
console.log(this.name);
console.log(name);

  我們看到var name = 'var-name';name = 'name'; 是定義的局部變量;

  而global.name='global-name';是為 全局對(duì)象定義一個(gè)name 屬性,

  而 this.name = 'module-name';是為模塊對(duì)象定義了一個(gè)name 屬性

  那么我們來驗(yàn)證一下,將下面保存成test2.js,運(yùn)行

復(fù)制代碼 代碼如下:

var t1 = require('./test1'); 
console.log(t1.name); 
console.log(global.name);

  從結(jié)果可以看出,我們成功導(dǎo)入 了test1 模塊,并運(yùn)行了 test1的代碼,因?yàn)樵趖est2 中 輸出 了global.name,

  而 t1.name 則是 test1 模塊中通過this.name 定義的,說明this 指向 的是 模塊作用域?qū)ο蟆?/p>

  exports與module.exports的一點(diǎn)區(qū)別

    Module.exports才是真正的接口,exports只不過是它的一個(gè)輔助工具。最終返回給調(diào)用的是Module.exports而不是exports。

    所有的exports收集到的屬性和方法,都賦值給了Module.exports。當(dāng)然,這有個(gè)前提,就是Module.exports本身不具備任何屬性和方法。

    如果,Module.exports已經(jīng)具備一些屬性和方法,那么exports收集來的信息將被忽略。

  舉個(gè)栗子:

    新建一個(gè)文件 bb.js

復(fù)制代碼 代碼如下:

exports.name = function() {
    console.log('My name is 大熊 !') ;
} ;

    創(chuàng)建一個(gè)測(cè)試文件 test.js

  

復(fù)制代碼 代碼如下:

var bb= require('./bb.js');
bb.name(); // 'My name is 大熊 !'

    修改bb.js如下:

復(fù)制代碼 代碼如下:

module.exports = 'BigBear!' ;
exports.name = function() {
    console.log('My name is 大熊 !') ;
} ;

  再次引用執(zhí)行bb.js

復(fù)制代碼 代碼如下:

var bb= require('./bb.js');
bb.name(); // has no method 'name'

  由此可知,你的模塊并不一定非得返回“實(shí)例化對(duì)象”。你的模塊可以是任何合法的javascript對(duì)象--boolean, number, date, JSON, string, function, array等等。

 (4),setTimeout,setInterval,process.nextTick,setImmediate

  以下以總結(jié)的形式出現(xiàn)

    Nodejs的特點(diǎn)是事件驅(qū)動(dòng),異步I/O產(chǎn)生的高并發(fā),產(chǎn)生此特點(diǎn)的引擎是事件循環(huán),事件被分門別類地歸到對(duì)應(yīng)的事件觀察者上,比如idle觀察者,定時(shí)器觀察者,I/O觀察者等等,事件循環(huán)每次循環(huán)稱為Tick,每次Tick按照先后順序從事件觀察者中取出事件進(jìn)行處理。

   調(diào)用setTimeout()或setInterval()時(shí)創(chuàng)建的計(jì)時(shí)器會(huì)被放入定時(shí)器觀察者內(nèi)部的紅黑樹中,每次Tick時(shí),會(huì)從該紅黑樹中檢查定時(shí)器是否超過定時(shí)時(shí)間,超過的話,就立即執(zhí)行對(duì)應(yīng)的回調(diào)函數(shù)。setTimeout()和setInterval()都是當(dāng)定時(shí)器使用,他們的區(qū)別在于后者是重復(fù)觸發(fā),而且由于時(shí)間設(shè)的過短會(huì)造成前一次觸發(fā)后的處理剛完成后一次就緊接著觸發(fā)。

   由于定時(shí)器是超時(shí)觸發(fā),這會(huì)導(dǎo)致觸發(fā)精確度降低,比如用setTimeout設(shè)定的超時(shí)時(shí)間是5秒,當(dāng)事件循環(huán)在第4秒循到了一個(gè)任務(wù),它的執(zhí)行時(shí)間3秒的話,那么setTimeout的回調(diào)函數(shù)就會(huì)過期2秒執(zhí)行,這就是造成精度降低的原因。并且由于采用紅黑樹和迭代的方式保存定時(shí)器和判斷觸發(fā),較為浪費(fèi)性能。

   使用process.nextTick()所設(shè)置的所有回調(diào)函數(shù)都會(huì)放置在數(shù)組中,會(huì)在下一次Tick時(shí)所有的都立即被執(zhí)行,該操作較為輕量,時(shí)間精度高。

   setImmediate()設(shè)置的回調(diào)函數(shù)也是在下一次Tick時(shí)被調(diào)用,其和process.nextTick()的區(qū)別在于兩點(diǎn):

    1,他們所屬的觀察者被執(zhí)行的優(yōu)先級(jí)不一樣,process.nextTick()屬于idle觀察者,setImmediate()屬于check觀察者,idle的優(yōu)先級(jí)>check。

   2,setImmediate()設(shè)置的回調(diào)函數(shù)是放置在一個(gè)鏈表中,每次Tick只執(zhí)行鏈表中的一個(gè)回調(diào)。這是為了保證每次Tick都能快速地被執(zhí)行。

二,總結(jié)一下

  1,理解Global對(duì)象存在的意義

  2,exports與module.exports的一點(diǎn)區(qū)別

  3,Console的底層是什么構(gòu)建的(Process對(duì)象的高層封裝)

  4,setTimeout,setInterval,process.nextTick,setImmediate的區(qū)別

  5,NodeJS中的兩種作用域

相關(guān)文章

  • 利用n工具輕松管理Node.js的版本

    利用n工具輕松管理Node.js的版本

    我們?cè)跍y(cè)試寫的Nodejs的程序在不同Nodejs版本下是否能正常運(yùn)行,或是我們想要嘗試下最新版 Nodejs 的新特性,但常用的代碼需要舊版本的 Nodejs的時(shí)候就需要用 Node 版本管理工具,本文介紹的是利用n工具如何輕松管理Node.js的版本,需要的朋友可以參考下。
    2017-04-04
  • node.js中fs文件系統(tǒng)目錄操作與文件信息操作

    node.js中fs文件系統(tǒng)目錄操作與文件信息操作

    本篇文章給大家詳細(xì)分析了node.js中fs文件系統(tǒng)目錄操作與文件信息操作的方法以及代碼詳解,需要的讀者可以參考下。
    2018-02-02
  • Puppeteer解決SEO問題方法

    Puppeteer解決SEO問題方法

    這篇文章主要為大家介紹了Puppeteer解決SEO問題方法詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-03-03
  • Node.js中的async?和?await?關(guān)鍵字微任務(wù)和宏任務(wù)

    Node.js中的async?和?await?關(guān)鍵字微任務(wù)和宏任務(wù)

    這篇文章主要介紹了Node.js中的async和await關(guān)鍵字微任務(wù)和宏任務(wù),文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下
    2022-07-07
  • node.js下LDAP查詢實(shí)例分享

    node.js下LDAP查詢實(shí)例分享

    這篇文章主要介紹了node.js下LDAP查詢實(shí)例分享的相關(guān)資料,需要的朋友可以參考下
    2015-09-09
  • package.json配置文件構(gòu)成詳解

    package.json配置文件構(gòu)成詳解

    這篇文章主要介紹了package.json配置文件構(gòu)成以及相關(guān)知識(shí)點(diǎn)內(nèi)容,有興趣的朋友們可以學(xué)習(xí)下。
    2019-08-08
  • 使用Node.js實(shí)現(xiàn)一個(gè)多人游戲服務(wù)器引擎

    使用Node.js實(shí)現(xiàn)一個(gè)多人游戲服務(wù)器引擎

    這篇文章主要給大家介紹了關(guān)于如何使用Node.js實(shí)現(xiàn)一個(gè)多人游戲服務(wù)器引擎的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者使用Node.js具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-03-03
  • Nodejs爬蟲進(jìn)階教程之異步并發(fā)控制

    Nodejs爬蟲進(jìn)階教程之異步并發(fā)控制

    這篇文章主要介紹了Nodejs爬蟲進(jìn)階教程之異步并發(fā)控制的相關(guān)資料,需要的朋友可以參考下
    2016-02-02
  • nodejs個(gè)人博客開發(fā)第七步?后臺(tái)登陸

    nodejs個(gè)人博客開發(fā)第七步?后臺(tái)登陸

    這篇文章主要為大家詳細(xì)介紹了nodejs個(gè)人博客開發(fā)的后臺(tái)登陸功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-04-04
  • Windows8下搭建Node.js開發(fā)環(huán)境教程

    Windows8下搭建Node.js開發(fā)環(huán)境教程

    這篇文章主要介紹了Windows8下搭建Node.js開發(fā)環(huán)境教程,Win8下安裝node.js也比較簡單,只是一些權(quán)限比較麻煩,需要的朋友可以參考下
    2014-09-09

最新評(píng)論