亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > JavaScript > 正文

Nodejs學習筆記之Global Objects全局對象

2019-11-20 13:25:33
字體:
來源:轉載
供稿:網友

一,開篇分析

在上個章節中我們學習了NodeJS的基礎理論知識,對于這些理論知識來說理解是至關重要的,在后續的章節中,我們會對照著官方文檔逐步學習里面的各部分模塊,好了該是本文主角登臺亮相的時候了,Global

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

Global Objects全局對象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.

這些對象在所有的模塊中都可用。實際上有些對象并不在全局作用域范圍中,但是在它的模塊作用域中------這些會標識出來的。

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.

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

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

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

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

同時,也預先定義了一些全局方法及全局類Global對象就是NodeJS中的全局命名空間,任何全局變量,函數或對象都是該對象的一個屬性值。

在REPL運行環境中,你可以通過如下語句來觀察Global對象中的細節內容,見下圖:

我在下面會逐一說說掛載在Global對象上的相關屬性值對象。

(1),Process

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

  process {對象} 這是一個進程對象。 在后續的章節中我會細說,但在這里我要先拿出一個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.

  在事件循環的下一次循環中調用 callback 回調函數。這不是 setTimeout(fn, 0) 函數的一個簡單別名,因為它的效率高多了。

  該函數能在任何 I/O 事前之前調用我們的回調函數。如果你想要在對象創建之后而I/O 操作發生之前執行某些操作,那么這個函數對你而言就十分重要了。

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

   Node.js是單線程的,除了系統IO之外,在它的事件輪詢過程中,同一時間只會處理一個事件。你可以把事件輪詢想象成一個大的隊列,在每個時間點上,系統只會處理一個事件。

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

   在每個I/O型的應用中,你只需要給每一個輸入輸出定義一個回調函數即可,他們會自動加入到事件輪詢的處理隊列里。

  當I/O操作完成后,這個回調函數會被觸發。然后系統會繼續處理其他的請求。

  

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

復制代碼 代碼如下:

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

運行上面的代碼,你從下面終端打印的信息會看到,"bar"的輸出在“foo”的前面。這就驗證了上面的說法,foo()是在下一個時間點運行的。

復制代碼 代碼如下:

bar
foo

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

復制代碼 代碼如下:

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

  但在內部的處理機制上,process.nextTick()和setTimeout(fn, 0)是不同的,process.nextTick()不是一個單純的延時,他有更多的特性

  更精確的說,process.nextTick()定義的調用會創建一個新的子堆棧。在當前的棧里,你可以執行任意多的操作。但一旦調用netxTick,函數就必須返回到父堆棧。然后事件輪詢機制又重新等待處理新的事件,如果發現nextTick的調用,就會創建一個新的棧。

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

  在多個事件里交叉執行CPU運算密集型的任務:

  在下面的例子里有一個compute(),我們希望這個函數盡可能持續的執行,來進行一些運算密集的任務。

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

復制代碼 代碼如下:

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();

  在這種模式下,我們不需要遞歸的調用compute(),我們只需要在事件循環中使用process.nextTick()定義compute()在下一個時間點執行即可。

  在這個過程中,如果有新的http請求進來,事件循環機制會先處理新的請求,然后再調用compute()。

  反之,如果你把compute()放在一個遞歸調用里,那系統就會一直阻塞在compute()里,無法處理新的http請求了。你可以自己試試。

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

 ?。?),Console

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

  控制臺 {對象} 用于打印到標準輸出和錯誤輸出。看如下測試:

  

復制代碼 代碼如下:

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

  會得到以下輸出結果: 

復制代碼 代碼如下:

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));
  }
}

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

 (3),exports與module.exports

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

復制代碼 代碼如下:

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';是為 全局對象定義一個name 屬性,

  而 this.name = 'module-name';是為模塊對象定義了一個name 屬性

  那么我們來驗證一下,將下面保存成test2.js,運行

復制代碼 代碼如下:

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

  從結果可以看出,我們成功導入 了test1 模塊,并運行了 test1的代碼,因為在test2 中 輸出 了global.name,

  而 t1.name 則是 test1 模塊中通過this.name 定義的,說明this 指向 的是 模塊作用域對象。

  exports與module.exports的一點區別

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

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

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

  舉個栗子:

    新建一個文件 bb.js

復制代碼 代碼如下:

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

    創建一個測試文件 test.js

  

復制代碼 代碼如下:

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

    修改bb.js如下:

復制代碼 代碼如下:

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

  再次引用執行bb.js

復制代碼 代碼如下:

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

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

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

  以下以總結的形式出現

    Nodejs的特點是事件驅動,異步I/O產生的高并發,產生此特點的引擎是事件循環,事件被分門別類地歸到對應的事件觀察者上,比如idle觀察者,定時器觀察者,I/O觀察者等等,事件循環每次循環稱為Tick,每次Tick按照先后順序從事件觀察者中取出事件進行處理。

   調用setTimeout()或setInterval()時創建的計時器會被放入定時器觀察者內部的紅黑樹中,每次Tick時,會從該紅黑樹中檢查定時器是否超過定時時間,超過的話,就立即執行對應的回調函數。setTimeout()和setInterval()都是當定時器使用,他們的區別在于后者是重復觸發,而且由于時間設的過短會造成前一次觸發后的處理剛完成后一次就緊接著觸發。

   由于定時器是超時觸發,這會導致觸發精確度降低,比如用setTimeout設定的超時時間是5秒,當事件循環在第4秒循到了一個任務,它的執行時間3秒的話,那么setTimeout的回調函數就會過期2秒執行,這就是造成精度降低的原因。并且由于采用紅黑樹和迭代的方式保存定時器和判斷觸發,較為浪費性能。

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

   setImmediate()設置的回調函數也是在下一次Tick時被調用,其和process.nextTick()的區別在于兩點:

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

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

二,總結一下

  1,理解Global對象存在的意義

  2,exports與module.exports的一點區別

  3,Console的底層是什么構建的(Process對象的高層封裝)

  4,setTimeout,setInterval,process.nextTick,setImmediate的區別

  5,NodeJS中的兩種作用域

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
日韩精品亚洲元码| 国产精品成人观看视频国产奇米| 亚洲国产精品字幕| 亚洲成人亚洲激情| 精品国偷自产在线视频| 日本精品一区二区三区在线播放视频| 国产日韩欧美中文| 色婷婷综合成人av| 欧美第一黄网免费网站| 国产精品入口尤物| 中文字幕自拍vr一区二区三区| 热久久视久久精品18亚洲精品| 北条麻妃一区二区三区中文字幕| 久久精品国产亚洲| 欧美国产第二页| 日韩精品高清视频| 久久99国产精品久久久久久久久| 欧美性猛交xxxx| 中文字幕综合在线| 亚洲天堂男人天堂女人天堂| 国产精国产精品| 国产日韩精品在线| 亚洲欧美一区二区三区在线| 亚洲精品久久久久中文字幕欢迎你| 国产精品第二页| 亚洲无限乱码一二三四麻| 一区二区三区在线播放欧美| 国产91久久婷婷一区二区| 影音先锋欧美在线资源| 国产精品久久久久久亚洲调教| 亚洲2020天天堂在线观看| 欧美激情伊人电影| 欧美丰满少妇xxxxx做受| 亚洲综合av影视| 欧美午夜激情在线| 成人黄色av免费在线观看| 亚洲成人激情小说| 国产香蕉一区二区三区在线视频| 日韩免费在线播放| 在线观看欧美成人| 日韩中文字幕久久| 欧美视频免费在线观看| 亚洲人成自拍网站| 国产+人+亚洲| 国产精品h在线观看| 欧美日本高清视频| 久久久欧美一区二区| 91黄色8090| 国产69精品久久久久9| 成人羞羞国产免费| 色婷婷久久一区二区| 亚洲色图17p| 欧美日韩另类在线| 国产精品久久久久国产a级| 亚洲国产精品推荐| 欧美日韩成人在线视频| 91精品国产99久久久久久| 亚洲国产欧美久久| 精品久久久久久中文字幕大豆网| 亚洲精品国产精品自产a区红杏吧| 黄网站色欧美视频| 国产精品av网站| 亚洲欧洲视频在线| 久久精品中文字幕一区| 伦伦影院午夜日韩欧美限制| 青草青草久热精品视频在线观看| 亚洲xxx自由成熟| 欧美黑人视频一区| 久久久久久久成人| 亚洲中国色老太| 精品国产一区二区三区久久狼5月| 国产精品欧美久久久| 51视频国产精品一区二区| 俺也去精品视频在线观看| 成人在线免费观看视视频| 国产日韩专区在线| 国产小视频91| 久久91亚洲精品中文字幕| 亚洲男人天堂网站| 成人免费大片黄在线播放| 欧美精品videossex性护士| 成人免费视频xnxx.com| 欧美自拍视频在线观看| 国产精品一二三视频| 2021久久精品国产99国产精品| 2021久久精品国产99国产精品| 亚洲精品电影在线| 国产精品视频免费观看www| 97精品欧美一区二区三区| 在线播放国产一区中文字幕剧情欧美| 欧美精品成人在线| 欧美丝袜美女中出在线| 国产精品人成电影在线观看| 欧美日本精品在线| 美女国内精品自产拍在线播放| 欧美日韩国产激情| 欧美肥臀大乳一区二区免费视频| 欧美大全免费观看电视剧大泉洋| 在线观看欧美日韩国产| 亚洲自拍另类欧美丝袜| 欧美性猛交xxxx免费看漫画| 亚洲欧美日韩中文视频| 欧美亚洲国产视频| 亚洲石原莉奈一区二区在线观看| 日韩网站免费观看| 隔壁老王国产在线精品| 欧美精品18videos性欧美| 精品国产成人在线| 国产精品第100页| 亚洲另类xxxx| 亚洲一区二区三区乱码aⅴ蜜桃女| www高清在线视频日韩欧美| 自拍偷拍亚洲一区| 日韩电影在线观看永久视频免费网站| 久久成人人人人精品欧| 久久国产精品电影| 成人国产精品色哟哟| 91精品国产色综合久久不卡98口| 欧美精品在线极品| 亚洲va码欧洲m码| 亚洲国产另类 国产精品国产免费| 色婷婷综合久久久久中文字幕1| 精品成人乱色一区二区| 国外成人在线视频| 国产主播欧美精品| 97久久超碰福利国产精品…| 91精品国产高清自在线看超| 日韩电影中文字幕在线| 福利视频导航一区| 日韩免费观看av| 欧美日韩国产精品| 国产精品一区二区三区毛片淫片| 色午夜这里只有精品| 韩国一区二区电影| 国产女人精品视频| 欧美xxxx18性欧美| 久久视频在线免费观看| 亚洲2020天天堂在线观看| 欧美夫妻性生活xx| 亚洲国产私拍精品国模在线观看| 超碰91人人草人人干| 日韩av中文字幕在线| 神马国产精品影院av| 欧美激情啊啊啊| 亚洲一区美女视频在线观看免费| 国产成人精品在线播放| 国外色69视频在线观看| 亚洲人成77777在线观看网| 日本高清久久天堂| www.欧美三级电影.com| 亚洲v日韩v综合v精品v| 欧美日韩视频免费播放| 美女福利视频一区| 日韩成人av网址| 国产在线视频一区| 奇门遁甲1982国语版免费观看高清| 亚洲尤物视频网| 精品国产鲁一鲁一区二区张丽| 日韩亚洲综合在线| 日本高清不卡的在线| 久久精品一偷一偷国产| 国产精品直播网红| 国产日韩在线播放| 国产亚洲精品久久|