一文詳解Node中的模組化、檔案系統與環境變數

2022-12-28 22:03:20
本篇文章帶大家深入瞭解中的模組化、檔案系統與環境變數,有一定的參考價值,有需要的朋友可以參考一下,希望對大家有所幫助。

一、Node.js模組化

1.0、變數作用域

(1)、在瀏覽器端使用var或不使用關鍵字定義的變數屬於全域性作用域,也就是可以使用window物件存取。【相關教學推薦:、】

    <script>
      var a = 100;

      (function () {
        b = 200;
      })();

      console.log(window.a, a);
      console.log(window.b, b);
    </script>
登入後複製

結果:

(2)、在Node.js中沒有window物件

(3)、在Node.js的互動環境下,定義的變數屬於global,global是類似瀏覽器端的window物件

(4)、在模組中(檔案中)有global物件,使用關鍵字var,let,const定義的成員不屬於global物件,僅在當前模組中有效,而不使用關鍵字定義的物件屬於global物件。

var a=100;
b=200;
let c=300;
const d=400;
console.log(global);
console.log(global.a);
console.log(global.b);
console.log(global.c);
console.log(global.d);
登入後複製

終端輸出:

1.1、模組概要

早期的javascript版本沒有塊級作用域、沒有類、沒有包、也沒有模組,這樣會帶來一些問題,如複用、依賴、衝突、程式碼組織混亂等,隨著前端的膨脹,模組化顯得非常迫切。

前端模組化規範如下:

常見的的JavaScript模組規範有:CommonJS、AMD、CMD、UMD、原生模組化。

雖然我們學習過ES6的模組化但是ES6與NodeJS使用不同的模組化規範,單獨學習NodeJS的模組化非常有必要。

模組化是指解決一個複雜問題時,自頂向下逐層把系統劃分成若干模組的過程。對於整個系統來說,模組是可組合、分解和更換 的單元。

JavaScript在早期的設計中就沒有模組、包、類的概念,開發者需要模擬出類似的功能,來隔離、組織複雜的JavaScript程式碼,我們稱為模組化。

模組就是一個實現特定功能的檔案,有了模組我們就可以更方便的使用別人的程式碼,要用什麼功能就載入什麼模組

模組化開發的四點好處:

  (1)、 避免變數汙染,命名衝突

  (2)、提高程式碼複用率

  (3)、提高了可維護性

  (4)、方便依賴關係管理

nodejs中根據模組的來源不同,將模組分為了3大類,分別是:

  • 內建模組(內建模組是由Node.js官方提供的,例如fs、path、http等)
  • 自定義模組 (使用者建立的每個 .js檔案,都是自定義模組)
  • 第三方模組 (由第三方開發出來的模組,並非官方提供的內建模組,也不是使用者建立的自定義模組,使用前需要先下載)

模組作用域。

和函數作用域類似,在自定義模組中定義的變數、方法等成員,只能在當前模組內被存取,這種模組級別的存取限制,叫做模組作用域。

模組作用域的好處:防止了全域性變數汙染的問題

1.2、CommonJS

CommonJS就是一個JavaScript模組化的規範,該規範最初是用在伺服器端NodeJS中,前端的webpack也是對CommonJS原生支援的。

根據這個規範

(1)、每一個檔案就是一個模組其內部定義的變數是屬於這個模組的,不會對外暴露,也就是說不會汙染全域性變數。

(2)、匯入自定義的模組時路徑需要以./或../開始,同一路徑下也不能省略。

(3)、如果反覆多次require模組,只載入一次。

(4)、require引入模組時,字尾名.js可以省略

(5)、每個模組檔案都是一個獨立的函數級作用域,在其它模組中不能直接存取

m1.js:

console.log("這是模組m1");
let a=100;
b=200;
登入後複製

m2.js

var m11=require("./m1");
console.log(a);
console.log(b);
登入後複製

結果:

從上面的範例可以看出a在模組2中是存取不到的,模組其實就是一個封閉的函數:

m1.js的程式碼如下:

console.log("這是模組m1");
let a=100;
b=200;
//輸出當前函數
console.log(arguments.callee+"");
登入後複製

實際輸出結果:

function (exports, require, module, __filename, __dirname) {
console.log("這是模組m1");
let a=100;
b=200;
//輸出當前函數
console.log(arguments.callee+"");
}
登入後複製

(6)、每個模組中都包含如下5個物件:

exports:匯出物件,預設為{}

require:匯入函數,使用該函數可以實現模組的依賴

module:模組資訊,用於記錄當前模組的所有資訊

__filename:當前模組的檔案全路徑,含檔名

__dirname:當前模組的檔案路徑不含檔名

(7)、使用exports或module.exports物件可以將當前模組中需要匯出的內容暴露出去。

m1.js

let a=100;
let b=()=>{
    return 200;
};

exports.a=a;
exports.b=b;
登入後複製

m2.js

const m1=require("./m1");
console.log(m1);
console.log(m1.a);
console.log(m1.b());
登入後複製

結果:

(8)、匯入模組內容可以結合結構語法

m1.js

exports.a=100;
exports.b=function(){
    return 200;
};
登入後複製

m2.js

const {a,b:fun}=require("./m1");
console.log(a);
console.log(fun());
登入後複製

結果:

1.3、NodeJS中使用CommonJS模組管理

CommonJS的核心思想就是通過 require 方法來同步載入所要依賴的其他模組,然後通過 exports 或者 module.exports 來匯出需要暴露的介面。

CommonJS API編寫應用程式,然後這些應用可以執行在不同的JavaScript直譯器和不同的主機環境中。

2009年,美國程式設計師Ryan Dahl創造了node.js專案,將javascript語言用於伺服器端程式設計。這標誌"Javascript模組化程式設計"正式誕生。因為老實說,在瀏覽器環境下,以前沒有模組也不是特別大的問題,畢竟網頁程式的複雜性有限;但是在伺服器端,一定要有模組,與作業系統和其他應用程式互動,否則根本沒法程式設計。NodeJS是CommonJS規範的實現,webpack 也是以CommonJS的形式來書寫。

CommonJS定義的模組分為:{模組參照(require)} {模組定義(exports)} {模組標識(module)}
//require()用來引入外部模組;
//exports物件用於匯出當前模組的方法或變數,唯一的匯出口;
//module物件就代表模組本身。
登入後複製

Nodejs的模組是基於CommonJS規範實現的,通過轉換也可以執行在瀏覽器端。

特點:

1、所有程式碼都執行在模組作用域,不會汙染全域性作用域。
2、模組可以多次載入,但是隻會在第一次載入時執行一次,然後執行結果就被快取了,以後再載入,就直接讀取快取結果。要想讓模組再次執行,必須清除快取。
3、模組載入的順序,按照其在程式碼中出現的順序。

1.3.1、模組定義

根據commonJS規範,一個單獨的檔案是一個模組每一個模組都是一個單獨的作用域,也就是說,在該模組內部定義的變數,無法被其他模組讀取,除非為global物件的屬性

模組擁有像函數一樣的函數級作用域:

  • 每個模組內部,module變數代表當前模組

  • module變數是一個物件,它的exports屬性(即module.exports)是對外的介面

  • 載入某個模組,其實是載入該模組的module.exports屬性。require()方法用於載入模組。

模組只有一個出口,module.exports物件,我們需要把模組希望輸出的內容放入該物件。

mathLib.js模組定義

var message="Hello CommonJS!";

module.exports.message=message;
module.exports.add=(m,n)=>console.log(m+n);
登入後複製

在 Node.js 中,建立一個模組非常簡單,如下我們建立一個 'main.js' 檔案,程式碼如下:

var hello = require('./hello');
hello.world();
登入後複製

以上範例中,程式碼 require('./hello') 引入了當前目錄下的hello.js檔案(./ 為當前目錄,node.js預設字尾為js)。

Node.js 提供了exports 和 require 兩個物件,其中 exports 是模組公開的介面,require 用於從外部獲取一個模組的介面,即所獲取模組的 exports 物件。

接下來我們就來建立hello.js檔案,程式碼如下:

exports.world = function() {
  console.log('Hello World');
}
登入後複製

在以上範例中,hello.js 通過 exports 物件把 world 作為模組的訪 問介面,在 main.js 中通過 require('./hello') 載入這個模組,然後就可以直接訪 問main.js 中 exports 物件的成員函數了。

有時候我們只是想把一個物件封裝到模組中,格式如下:

module.exports = function() {  // ...}
登入後複製

例如:

//hello.js 
function Hello() { 
    varname; 
    this.setName = function(thyName) { 
        name = thyName; 
    }; 
    this.sayHello = function() { 
        console.log('Hello ' + name); 
    }; 
}; 
module.exports = Hello;
登入後複製

這樣就可以直接獲得這個物件了:

//main.js 
var Hello = require('./hello'); 
hello = new Hello(); 
hello.setName('BYVoid'); 
hello.sayHello();
登入後複製

模組介面的唯一變化是使用 module.exports = Hello 代替了exports.world = function(){}。 在外部參照該模組時,其介面物件就是要輸出的 Hello 物件本身,而不是原先的 exports。

1.3.2、模組依賴

載入模組用require方法,該方法讀取一個檔案並且執行,返回檔案內部的module.exports物件。

在用require載入自定義模組期間,可以省略.js這個字尾名。

myApp.js 模組依賴

var math=require('./mathLib');
console.log(math.message);
math.add(333,888);
登入後複製

3、測試執行

安裝好node.JS

開啟控制檯,可以使用cmd命令,也可以直接在開發工具中存取

執行

1.3.3、內建模組載入

也許你已經注意到,我們已經在程式碼中使用了模組了。像這樣:

var http = require("http");

...

http.createServer(...);
登入後複製

Node.js中自帶了一個叫做"http"的模組,我們在我們的程式碼中請求它並把返回值賦給一個本地變數。

這把我們的本地變數變成了一個擁有所有 http 模組所提供的公共方法的物件。

Node.js 的 require方法中的檔案查詢策略如下:

由於Node.js中存在4類模組(原生模組和3種檔案模組),儘管require方法極其簡單,但是內部的載入卻是十分複雜的,其載入優先順序也各自不同。如下圖所示:

從檔案模組快取中載入

儘管原生模組與檔案模組的優先順序不同,但是都不會優先於從檔案模組的快取中載入已經存在的模組。

從原生模組載入

原生模組的優先順序僅次於檔案模組快取的優先順序。require方法在解析檔名之後,優先檢查模組是否在原生模組列表中。以http模組為例,儘管在目錄下存在一個http/http.js/http.node/http.json檔案,require("http")都不會從這些檔案中載入,而是從原生模組中載入。

原生模組也有一個快取區,同樣也是優先從快取區載入。如果快取區沒有被載入過,則呼叫原生模組的載入方式進行載入和執行。

從檔案載入

當檔案模組快取中不存在,而且不是原生模組的時候,Node.js會解析require方法傳入的引數,並從檔案系統中載入實際的檔案,載入過程中的包裝和編譯細節在前一節中已經介紹過,這裡我們將詳細描述查詢檔案模組的過程,其中,也有一些細節值得知曉。

require方法接受以下幾種引數的傳遞:

  • http、fs、path等,原生模組。
  • ./mod或../mod,相對路徑的檔案模組。
  • /pathtomodule/mod,絕對路徑的檔案模組。
  • mod,非原生模組的檔案模組。

node_modules資料夾用來存放所有已安裝到專案中的包。require()匯入第三方包時,就是從這個目錄中查詢並載入包。

package-lock.json組態檔用來記錄node_modules目錄下的每一個包的下載資訊,例如包的名字、版本號、下載地址等。

注意:不要手動修改node_modules或package-lock.json檔案中的任何程式碼,npm包管理工具會自動維護它們。

1.3.4、module物件

在每個.js自定義模組中都有一個module物件,它裡面儲存了和當前模組有關的資訊

每個模組內部,module變數代表當前模組
module變數是一個物件,它的exports屬性(即module.exports)是對外的介面
載入某個模組,其實是載入該模組的module.exports屬性。require()方法用於載入模組。

二、Node.js 檔案系統

Node.js 提供一組類似 UNIX(POSIX)標準的檔案操作API。 Node 匯入檔案系統模組(fs)語法如下所示:

var fs = require("fs")
登入後複製

2.1、非同步和同步

Node.js 檔案系統(fs 模組)模組中的方法均有非同步和同步版本,例如讀取檔案內容的函數有非同步的 fs.readFile() 和同步的 fs.readFileSync()。

非同步的方法函數最後一個引數為回撥函數,回撥函數的第一個引數包含了錯誤資訊(error)。

建議大家是用非同步方法,比起同步,非同步方法效能更高,速度更快,而且沒有阻塞。

範例

建立 input.txt 檔案,內容如下:

foo
登入後複製

建立 filereaddemo.js 檔案, 程式碼如下:

const fs=require("fs");  //依賴內建模組fs,用於檔案管理

//非同步讀取檔案students.txt,設定讀取成功時的回撥函數,err表示錯誤資訊,data表示資料
fs.readFile("students.txt",function(err,data){
    if(err) throw err;
    console.log("非同步:"+data+"");
});

console.log("---------------");

//同步讀取
let data=fs.readFileSync("students.txt");
console.log("同步:"+data+"");
登入後複製

以上程式碼執行結果如下:

接下來,讓我們來具體瞭解下 Node.js 檔案系統的方法。

2.2、獲取檔案資訊

以下為通過非同步模式獲取檔案資訊的語法格式:

fs.stat(path, callback)
登入後複製

引數使用說明如下:

  • path - 檔案路徑。

  • callback - 回撥函數,帶有兩個引數如:(err, stats), stats 是 fs.Stats 物件。

fs.stat(path)執行後,會將stats類的範例返回給其回撥函數。可以通過stats類中的提供方法判斷檔案的相關屬性。例如判斷是否為檔案:

const fs=require("fs");

fs.stat("students.txt",(err,stats)=>{
    console.log("是檔案嗎?"+stats.isFile());
    console.log("是目錄嗎?"+stats.isDirectory());
    console.log(stats);
});
登入後複製

結果:

stats類中的方法有:

方法描述
stats.isFile()如果是檔案返回 true,否則返回 false。
stats.isDirectory()如果是目錄返回 true,否則返回 false。
stats.isBlockDevice()如果是塊裝置返回 true,否則返回 false。
stats.isCharacterDevice()如果是字元裝置返回 true,否則返回 false。
stats.isSymbolicLink()如果是軟連結返回 true,否則返回 false。
stats.isFIFO()如果是FIFO,返回true,否則返回 false。FIFO是UNIX中的一種特殊型別的命令管道。
stats.isSocket()如果是 Socket 返回 true,否則返回 false。

接下來我們建立 file.js 檔案,程式碼如下所示:

var fs = require("fs");

console.log("準備開啟檔案!");
fs.stat('input.txt', function (err, stats) {
   if (err) {
       return console.error(err);
   }
   console.log(stats);
   console.log("讀取檔案資訊成功!");

   // 檢測檔案型別
   console.log("是否為檔案(isFile) ? " + stats.isFile());
   console.log("是否為目錄(isDirectory) ? " + stats.isDirectory());    
});
登入後複製

以上程式碼執行結果如下:

$ node file.js
準備開啟檔案!
{ dev: 16777220,
  mode: 33188,
  nlink: 1,
  uid: 501,
  gid: 20,
  rdev: 0,
  blksize: 4096,
  ino: 40333161,
  size: 61,
  blocks: 8,
  atime: Mon Sep 07 2015 17:43:55 GMT+0800 (CST),
  mtime: Mon Sep 07 2015 17:22:35 GMT+0800 (CST),
  ctime: Mon Sep 07 2015 17:22:35 GMT+0800 (CST) }
讀取檔案資訊成功!
是否為檔案(isFile) ? true
是否為目錄(isDirectory) ? false
登入後複製

2.3、寫入檔案

以下為非同步模式下寫入檔案的語法格式:

fs.writeFile(filename, data[, options], callback)
登入後複製

如果檔案存在,該方法寫入的內容會覆蓋舊的檔案內容。

引數使用說明如下:

  • path - 檔案路徑。

  • data - 要寫入檔案的資料,可以是 String(字串) 或 Buffer(流) 物件。

  • options - 該引數是一個物件,包含 {encoding, mode, flag}。預設編碼為 utf8, 模式為 0666 , flag 為 'w'

  • callback - 回撥函數,回撥函數只包含錯誤資訊引數(err),在寫入失敗時返回。

接下來我們建立 file.js 檔案,程式碼如下所示:

const fs=require("fs");

fs.writeFile("output1.txt","非同步hello","utf-8",function(err){
    if(!err){
        console.log("非同步檔案寫入成功!");
    }
    else{
        throw err;
    }
});
console.log("---------------");
fs.writeFileSync("output2.txt","同步hello","utf-8");
console.log("同步檔案寫入成功");
登入後複製

以上程式碼執行結果如下:

2.4、刪除檔案

以下為刪除檔案的語法格式:

fs.unlink(path, callback)
登入後複製

引數使用說明如下:

  • path - 檔案路徑。

  • callback - 回撥函數,沒有引數。

接下來我們建立 file.js 檔案,程式碼如下所示:

const fs=require("fs");

fs.unlink("output1.txt",function(err){
    if(err){
        throw err;
    }
    else{
        console.log("非同步刪除檔案成功!");
    }
});
console.log("--------------------");
fs.unlinkSync("output2.txt");
console.log("同步刪除檔案成功!");
登入後複製

以上程式碼執行結果如下:

2.5、建立目錄

以下為建立目錄的語法格式:

fs.mkdir(path[, mode], callback)
登入後複製

引數使用說明如下:

  • path - 檔案路徑。

  • mode - 設定目錄許可權,預設為 0777。

  • callback - 回撥函數,沒有引數。

接下來我們建立mkdirfile.js 檔案,程式碼如下所示:

const fs=require("fs");

fs.mkdir("dir1",function(err){
    if(err){
        throw err;
    }
    else{
        console.log("非同步建立目錄成功!");
    }
});
console.log("---------------------");
fs.mkdirSync("dir2");
console.log("同步建立目錄成功!");
登入後複製

以上程式碼執行結果如下:

2.6、讀取目錄

以下為讀取目錄的語法格式:

fs.readdir(path, callback)
登入後複製

引數使用說明如下:

  • path - 檔案路徑。

  • callback - 回撥函數,回撥函數帶有兩個引數err, files,err 為錯誤資訊,files 為 目錄下的檔案陣列列表。

接下來我們建立 file.js 檔案,程式碼如下所示:

const fs=require("fs");

fs.readdir("dir1",(err,files)=>{
    if(err) 
    {throw err;}
    else{
        console.log("非同步獲取目錄下的檔案成功!");
        files.forEach(file=>console.log(file));
    }
});
console.log("-----------------------");
let files=fs.readdirSync("dir2");
console.log("同步獲取目錄下的檔案成功!");
files.forEach(file=>console.log(file));
登入後複製

以上程式碼執行結果如下:

2.7、刪除目錄

以下為刪除目錄的語法格式:

fs.rmdir(path, callback)
登入後複製

引數使用說明如下:

  • path - 檔案路徑。

  • callback - 回撥函數,沒有引數。

接下來我們建立 file.js 檔案,程式碼如下所示:

var fs = require("fs");

console.log("準備刪除目錄 /tmp/test");
fs.rmdir("/tmp/test",function(err){
   if (err) {
       return console.error(err);
   }
   console.log("讀取 /tmp 目錄");
   fs.readdir("/tmp/",function(err, files){
      if (err) {
          return console.error(err);
      }
      files.forEach( function (file){
          console.log( file );
      });
   });
});
登入後複製

以上程式碼執行結果如下:

$ node file.js
準備刪除目錄 /tmp/test
input.out
output.out
test
test.txt
讀取 /tmp 目錄
……
登入後複製

2.8、檔案模組方法參考手冊

以下為 Node.js 檔案模組相同的方法列表:

方法描述
fs.rename(oldPath, newPath, callback)非同步 rename().回撥函數沒有引數,但可能丟擲異常。
fs.ftruncate(fd, len, callback)非同步 ftruncate().回撥函數沒有引數,但可能丟擲異常。
fs.ftruncateSync(fd, len)同步 ftruncate()
fs.truncate(path, len, callback)非同步 truncate().回撥函數沒有引數,但可能丟擲異常。
fs.truncateSync(path, len)同步 truncate()
fs.chown(path, uid, gid, callback)非同步 chown().回撥函數沒有引數,但可能丟擲異常。
fs.chownSync(path, uid, gid)同步 chown()
fs.fchown(fd, uid, gid, callback)非同步 fchown().回撥函數沒有引數,但可能丟擲異常。
fs.fchownSync(fd, uid, gid)同步 fchown()
fs.lchown(path, uid, gid, callback)非同步 lchown().回撥函數沒有引數,但可能丟擲異常。
fs.lchownSync(path, uid, gid)同步 lchown()
fs.chmod(path, mode, callback)非同步 chmod().回撥函數沒有引數,但可能丟擲異常。
fs.chmodSync(path, mode)同步 chmod().
fs.fchmod(fd, mode, callback)非同步 fchmod().回撥函數沒有引數,但可能丟擲異常。
fs.fchmodSync(fd, mode)同步 fchmod().
fs.lchmod(path, mode, callback)非同步 lchmod().回撥函數沒有引數,但可能丟擲異常。Only available on Mac OS X.
fs.lchmodSync(path, mode)同步 lchmod().
fs.stat(path, callback)非同步 stat(). 回撥函數有兩個引數 err, stats,stats 是 fs.Stats 物件。
fs.lstat(path, callback)非同步 lstat(). 回撥函數有兩個引數 err, stats,stats 是 fs.Stats 物件。
fs.fstat(fd, callback)非同步 fstat(). 回撥函數有兩個引數 err, stats,stats 是 fs.Stats 物件。
fs.statSync(path)同步 stat(). 返回 fs.Stats 的範例。
fs.lstatSync(path)同步 lstat(). 返回 fs.Stats 的範例。
fs.fstatSync(fd)同步 fstat(). 返回 fs.Stats 的範例。
fs.link(srcpath, dstpath, callback)非同步 link().回撥函數沒有引數,但可能丟擲異常。
fs.linkSync(srcpath, dstpath)同步 link().
fs.symlink(srcpath, dstpath[, type], callback)非同步 symlink().回撥函數沒有引數,但可能丟擲異常。 type 引數可以設定為 'dir', 'file', 或 'junction' (預設為 'file') 。
fs.symlinkSync(srcpath, dstpath[, type])同步 symlink().
fs.readlink(path, callback)非同步 readlink(). 回撥函數有兩個引數 err, linkString。
fs.realpath(path[, cache], callback)非同步 realpath(). 回撥函數有兩個引數 err, resolvedPath。
fs.realpathSync(path[, cache])同步 realpath()。返回絕對路徑。
fs.unlink(path, callback)非同步 unlink().回撥函數沒有引數,但可能丟擲異常。
fs.unlinkSync(path)同步 unlink().
fs.rmdir(path, callback)非同步 rmdir().回撥函數沒有引數,但可能丟擲異常。
fs.rmdirSync(path)同步 rmdir().
fs.mkdir(path[, mode], callback)S非同步 mkdir(2).回撥函數沒有引數,但可能丟擲異常。 mode defaults to 0777.
fs.mkdirSync(path[, mode])同步 mkdir().
fs.readdir(path, callback)非同步 readdir(3). 讀取目錄的內容。
fs.readdirSync(path)同步 readdir().返回檔案陣列列表。
fs.close(fd, callback)非同步 close().回撥函數沒有引數,但可能丟擲異常。
fs.closeSync(fd)同步 close().
fs.open(path, flags[, mode], callback)非同步開啟檔案。
fs.openSync(path, flags[, mode])同步 version of fs.open().
fs.utimes(path, atime, mtime, callback)?
fs.utimesSync(path, atime, mtime)修改檔案時間戳,檔案通過指定的檔案路徑。
fs.futimes(fd, atime, mtime, callback)?
fs.futimesSync(fd, atime, mtime)修改檔案時間戳,通過檔案描述符指定。
fs.fsync(fd, callback)非同步 fsync.回撥函數沒有引數,但可能丟擲異常。
fs.fsyncSync(fd)同步 fsync.
fs.write(fd, buffer, offset, length[, position], callback)將緩衝區內容寫入到通過檔案描述符指定的檔案。
fs.write(fd, data[, position[, encoding]], callback)通過檔案描述符 fd 寫入檔案內容。
fs.writeSync(fd, buffer, offset, length[, position])同步版的 fs.write()。
fs.writeSync(fd, data[, position[, encoding]])同步版的 fs.write().
fs.read(fd, buffer, offset, length, position, callback)通過檔案描述符 fd 讀取檔案內容。
fs.readSync(fd, buffer, offset, length, position)同步版的 fs.read.
fs.readFile(filename[, options], callback)非同步讀取檔案內容。
fs.readFileSync(filename[, options])
fs.writeFile(filename, data[, options], callback)非同步寫入檔案內容。
fs.writeFileSync(filename, data[, options])同步版的 fs.writeFile。
fs.appendFile(filename, data[, options], callback)非同步追加檔案內容。
fs.appendFileSync(filename, data[, options])The 同步 version of fs.appendFile.
fs.watchFile(filename[, options], listener)檢視檔案的修改。
fs.unwatchFile(filename[, listener])停止檢視 filename 的修改。
fs.watch(filename[, options][, listener])檢視 filename 的修改,filename 可以是檔案或目錄。返回 fs.FSWatcher 物件。
fs.exists(path, callback)檢測給定的路徑是否存在。
fs.existsSync(path)同步版的 fs.exists.
fs.access(path[, mode], callback)測試指定路徑使用者許可權。
fs.accessSync(path[, mode])同步版的 fs.access。
fs.createReadStream(path[, options])返回ReadStream 物件。
fs.createWriteStream(path[, options])返回 WriteStream 物件。
fs.symlink(srcpath, dstpath[, type], callback)非同步 symlink().回撥函數沒有引數,但可能丟擲異常。

更多內容,請檢視官網檔案模組描述:。

三、引數與環境變數

3.0、讀取自定義組態檔資料

創立一個 config 目錄並向其中增加一個 config/default.json 檔案。這將是預設組態檔,並將蘊含所有預設環境變數。

在咱們的範例應用程式中它應該是這樣的:

config/default.json

{
    "student":{
        "name":"tom",
        "age":19
    }
}
登入後複製

先依賴模組config,

npm i config
登入後複製

咱們將在咱們的應用程式中通過匯入 config 和應用 get 辦法拜訪變數來存取它。

const config=require("config");
console.log(config.get("student.name"));
console.log(config.get("student.age"));
登入後複製

執行結果:

3.1、讀取package.json設定引數

用於新增命令列的環境變數

package.json 可以設定config
指令碼中 (see npm-scripts) package.json 「config」 欄位會被環境變數覆蓋
<name>[@<version>]:<key>
例如,下面的package.json:
程式碼中使用 process.env['npm_package_config_xxxxxx'] 獲取設定的內容

package.json

{
  "name": "demo06",
  "config": {
    "foo": "123456"
  },
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start":"node configtest.js"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "config": "^3.3.7"
  }
}
登入後複製

configtest.js

console.log(process.env.npm_package_config_foo);
登入後複製

直接執行(node configtest.js)結果:

直接在命令列執行 node configtest,會輸出undefined

使用 npm run start,會輸出 123456

npm 設定包的config

npm config set foo = 3000 就可以修改預設的設定內容

然後再執行 npm test 會輸出 3000

3.2、環境變數的設定與讀取

檔案.env

USER_ID="239482"
USER_KEY="foobar"
NODE_ENV="development"
登入後複製

m3.js

npm i dotenv //依賴模組

require("dotenv").config();
console.log(process.env.USER_ID);
登入後複製

輸出結果:

239482

3.3、獲取系統中的環境變數

命令列下操作環境變數

3.3.1、檢視當前所有可用的環境變數

輸入 set 即可檢視。

3.3.2、檢視某個環境變數

輸入 「set 變數名」即可。比如想檢視path變數的值,即輸入 set path

3.3.3、修改環境變數

注意:所有的在cmd命令列下對環境變數的修改只對當前視窗有效,不是永久性的修改。也就是說當關閉此cmd命令列視窗後,將不再起作用。

永久性修改環境變數的方法有兩種:一種是直接修改登入檔,另一種是通過我的電腦-〉屬性-〉高階,來設定系統的環境變數(檢視詳細)。

1、修改環境變數

輸入 「set 變數名=變數內容」即可。比如將path設定為「d:\nmake.exe」,只要輸入set path="d:\nmake.exe"。

注意,此修改環境變數是指用現在的內容去覆蓋以前的內容,並不是追加。比如當我設定了上面的path路徑之後,如果我再重新輸入set path="c",再次檢視path路徑的時候,其值為「c:」,而不是「d:\nmake.exe」;「c」。

2、設定為空:

如果想將某一變數設定為空,輸入「set 變數名=」即可。

如「set path=」 那麼檢視path的時候就為空。注意,上面已經說了,只在當前命令列視窗起作用。因此檢視path的時候不要去右擊「我的電腦」——「屬性」........

3、給變數追加內容

輸入「set 變數名=%變數名%;變數內容」。(不同於3,那個是覆蓋)。如,為path新增一個新的路徑,輸入「 set path=%path%;d:\nmake.exe」即可將d:\nmake.exe新增到path中,再次執行"set path=%path%;c:",那麼,使用set path語句來檢視的時候,將會有:d:\nmake.exe;c:,而不是像第3步中的只有c:。

3.3.4、一些常用的環境變數

  • %AllUsersProfile%: 區域性 返回所有「使用者組態檔」的位置。 {所有使用者檔案目錄 – C:\Documents and Settings\All Users}
  • %AppData%: 區域性 返回預設情況下應用程式儲存資料的位置。 {當前使用者資料資料夾 – C:\Documents and Settings\wy\Application Data}
  • %Cd%: 區域性 返回當前目錄字串。
  • %CmdCmdLine%: 區域性 返回用來啟動當前的 Cmd.exe 的準確命令列。
  • %CmdExtVersion%: 系統 返回當前的「命令處理程式擴充套件」的版本號。
  • %CommonProgramFiles%: {檔案通用目錄 – C:\Program Files\Common Files}
  • %ComputerName%: 系統 返回計算機的名稱。 {計算機名 – IBM-B63851E95C9}
  • %ComSpec%: 系統 返回命令列直譯器可執行程式的準確路徑。 C:\WINDOWS\system32\cmd.exe
  • %Date%: 系統 返回當前日期。使用與 date /t 命令相同的格式。由 Cmd.exe 生成。有關 date 命令的詳細資訊,請參閱 Date。
  • %ErrorLevel%: 系統 返回最近使用過的命令的錯誤程式碼。通常用非零值表示錯誤。
  • %HomeDrive%: 系統 返回連線到使用者主目錄的本地工作站驅動器號。基於主目錄值的設定。使用者主目錄是在「本地使用者和組」中指定的。 {當前使用者根目錄 – C:}
  • %HomePath%: 系統 返回使用者主目錄的完整路徑。基於主目錄值的設定。使用者主目錄是在「本地使用者和組」中指定的。 {當前使用者路徑 – \Documents and Settings\wy}
  • %HomeShare%: 系統 返回使用者的共用主目錄的網路路徑。基於主目錄值的設定。使用者主目錄是在「本地使用者和組」中指定的。
  • %LogonSever%: 區域性 返回驗證當前登入對談的域控制器的名稱。
  • %Number_Of_Processors%: 系統 指定安裝在計算機上的處理器的數目。 {處理器個數 – 1}
  • %Os%: 系統 返回作業系統的名稱。Windows 2000 將作業系統顯示為 Windows_NT。 {作業系統名 – Windows_NT}
  • %Path%: 系統 指定可執行檔案的搜尋路徑。
  • %PathExt%: 系統 返回作業系統認為可執行的副檔名的列表。
  • %Processor_Architecture%: 系統 返回處理器的晶片體系結構。值: x86,IA64。 {處理器晶片架構 – x86}
  • %Processor_Identfier%: 系統 返回處理器說明。
  • %Processor_Level%: 系統 返回計算機上安裝的處理器的型號。 {處理器型號 – 6}
  • %Processor_Revision%: 系統 返回處理器修訂號的系統變數。 {處理器修訂號 – 0905}
  • %ProgramFiles%: {程式預設安裝目錄 – C:\Program Files}
  • %Prompt%: 區域性 返回當前解釋程式的命令提示字元設定。由 Cmd.exe 生成。 $P$G
  • %Random%: 系統 返回 0 到 32767 之間的任意十進位制數位。由 Cmd.exe 生成。
  • %SystemDrive%: 系統 返回包含 Windows XP 根目錄(即系統根目錄)的驅動器。 {系統根目錄 – C:}
  • %SystemRoot%: 系統 返回 Windows XP 根目錄的位置。 {系統目錄 – C:\WINDOWS}
  • %Temp%: 系統和使用者 返回對當前登入使用者可用的應用程式所使用的預設臨時目錄。有些應用程式需要 TEMP,而其它應用程式則需要 TMP。 {當前使用者臨時資料夾 – C:\DOCUME~1\wy\LOCALS~1\Temp}
  • %Time%: 系統 返回當前時間。使用與 time /t 命令相同的格式。由 Cmd.exe 生成。9:16:25.05
  • %UserDomain%: 區域性 返回包含使用者帳戶的域的名稱。 {包含使用者帳號的域 – IBM-B63851E95C9}
  • %UserName%: 區域性 返回當前登入的使用者的名稱。 {當前使用者名稱 – wy}
  • %UserProfile%: 區域性 返回當前使用者的組態檔的位置。 {當前使用者目錄 – C:\Documents and Settings\wy}
  • %WinDir%: 系統 返回作業系統目錄的位置。 {系統目錄 – C:\WINDOWS}

假定當前的系統環境變數定義如下,注意JAVA_HOME:

m3.js

console.log(process.env.JAVA_HOME);
登入後複製

輸出:

a,b在系統中已定義好

注意當前的終端是cmd,不是powershell

這裡a輸出123的原因是修改成888後沒有重新啟動電腦。

四、作業

4.1、根據視訊完成每一個上課範例。

4.2、定義一個模組circle.js,中模組中定義兩個方法一個用於計算圓的周長,一個用於計算圓的面積,再定義一個模組main.js依賴模組circle.js,並呼叫模組中的兩個方法用於計算。

4.3、在組態檔package.json中定義好埠port與主機地址host,建立一個web伺服器,參照設定資訊,實現埠與主機地址的切換功能。

4.4、使用config的方式完成4.3

4.5、使用.env,dotenv的方式完成4.3

4.6、使用系統環境變數完成4.3

五、視訊

更多node相關知識,請存取:!

以上就是一文詳解Node中的模組化、檔案系統與環境變數的詳細內容,更多請關注TW511.COM其它相關文章!