之前一直以傳統后端的思維來寫nodejs的代碼,發現運行結果與我的同步思維方式不太一樣,所以需要全面將nodejs學習一下,此學習筆記適合后端同學學習nodejs的時候觀看,前端大佬可以多多指正,
環境變數
console.log(setTimeout);
console.log(setInterval);
console.log(setImmediate);
console.log(__filename); // 當前檔案的全名
console.log(__dirname); //
console.log(process); // 行程資訊,全域變數
process就是當前運行環境變數的集合體,例如process.argv就是獲取用戶輸入的引數
數學庫
與Java一樣,叫Math
Math.random(); // 回傳0~1的浮點數
模塊規范之exports和module.exports的關系
需要解決的問題:
腳本變多時,需要手動管理加載順序
不同腳本之間邏輯呼叫,需要通過全域變數的方式去交流,例如:JQUERY,將輸出放到全域變數中,然后由其他部分進行使用
沒有html怎么辦?
nodejs中使用CommonJs模塊規范,加載另一個js,用require函式來獲取即可,
// demo.js
console.log("-----------");
let lib = require('./lib');
console.log('---------',lib);
// lib.js
console.log('==========');
exports.hello = '++++++++++';
exports.word = '///////////////';
exports.add = function () {
console.log('1111111111111')
};
可以看見,模塊中定義模塊輸出的方式:默認會注入一個叫export的變數,在該變數上掛引數就相當于給當前被require物件里面附一個值,還可以掛函式,物件等,理論上就是在輸出物件中加物件,所以在exports中我們可以掛各種型別的結構
同時,對于exports來說,外面可以改變模塊里面的內容,是同一個參考,
// demo.js
console.log("-----------");
let lib = require('./lib');
lib.addd = '*******************';
console.log('---------',lib);
// lib.js
console.log('==========');
exports.hello = '++++++++++';
exports.word = '///////////////';
exports.add = function () {
console.log('1111111111111')
};
setTimeout(()=>{
console.log(exports)
},2000);
運行結果如下,可以看見修改了外面被require的物件,里面的exports物件也被修改了

特定地,如果希望被require出來的不是一個物件,而是一個方法,或者變數啥的,可以使用module.exports,但是會覆寫掉之前懟exports變數的修改,
// demo.js
console.log("-----------");
let lib = require('./lib');
console.log('---------',lib);
// lib.js
console.log('==========');
exports.hello = '++++++++++';
exports.word = '///////////////';
exports.add = function () {
console.log('1111111111111')
};
module.exports = function dsa() {
return '123'
};
最終列印的結果為

可以看到結果中exports變數的值并沒有被輸出出來,得到這樣的結果有兩種可能性,第一是module.exports將exports物件給覆寫掉了,第二種是module.exports和exports在檔案被require的時候其實是兩個不同的東西,指向兩個不同的記憶體,當模塊被require的時候,如果module.exports沒有被指定,那么就require出來的是exports物件,如果module.exports被指定了,那么就使用module,exports,我比較傾向于后面這種解釋,下面來證實我的觀點,
// demo.js
console.log("-----------");
let lib = require('./lib');
lib.addd = '*******************';
console.log('---------',lib);
// lib.js
console.log('==========');
exports.hello = '++++++++++';
exports.word = '///////////////';
exports.add = function () {
console.log('1111111111111')
};
setTimeout(()=>{
console.log(exports)
},2000);
module.exports = function dsa() {
return '123'
};
setTimeout(()=>{
console.log(module.exports)
},2000);
運行結果為:

可以看到,在demo.js中給參考的lib新增了addd屬性,最終是作用到了module.exports上,同時,exports列印的結果與module.exports并不一樣,說明,module.exports和exports不是一個物件,只是在一個模塊被參考時,module.exports的優先級要高于exports,
獲取控制臺輸入(標準輸入輸出)
process.stdin.on('data', (e) => {
const x = e.toString().trim();
console.log(x);
} );
包管理工具
每個語言都有包管理工具,不過nodejs有個坑,就是npm有時候版本和nodejs不匹配,這個時候就會拋出一些莫名其妙的錯誤,碰到這種情況,就只能去npm官網解決問題部分尋找結果了,
npm init
要使用npm,需要本身就是一個npm目錄,所以需要使用 npm init 來宣告為npm 包
package.json
dependencies:放在里面,npm install時會被自動下載,宣告當前npm包所有的依賴
安裝卸載
npm install xxx
npm uninstall xxx
國內鏡像
npm是國外的鏡像,可以使用淘寶的npm鏡像,可以去NPM鏡像查看相關的方法
值得注意的是,用cnpm的時候要加上--save指令,否則dependencies中不會加進去
npm search xxx
很多同學不知道自己適合用什么包,比如我想連接redis,該使用什么包呢?就可以使用 npm search redis來尋找了,相同的,docker search redis/composer search redis 等等都是這么玩的,
nodejs架構
基于V8運行環境
事件驅動:非阻塞式的IO模型
內置模塊
nodejs官方網站檔案頁面 nodejs官方網站檔案中文頁面
底層能力是怎么完成的
以os為例,在原始碼的lib檔案中:internalBinding('os') 在 src/node_os.cc中再呼叫v8的能力
Event模塊實作觀察者模式,進而使得兩個物件進行傳輸
EventEmitter,process繼承與它,所以可以往上拋事件,也就是典型的觀察者模式,底層的能力封裝起來放到一個模塊中,外面的模塊拿到這個代碼,通過事件的監聽器,就能比較方便的,知道子模塊里面發生的變化,
觀察者模式,可以用來解決兩個物件的交流問題,
其實這個方法也可以實作兩個函式的先后執行,從而將代碼程序化,我看到這個還是比較興奮的,這樣我就可以解決本來具有先后執行順序的代碼,由于nodejs的異步特性導致無法實作的,可以利用這個模式實作
const EventEmitter = require('events').EventEmitter;
class X extends EventEmitter{
constructor(){
super();
setInterval(()=>{
this.emit('newlesson',{
price:Math.random()*100
});
},3000)
}
}
const x = new X();
x.addListener('newlesson',(res)=>{
console.log('buy!',res);
});

本文由博客群發一文多發等運營工具平臺 OpenWrite 發布
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/187382.html
標籤:其他
上一篇:構建內網安全的威脅與方法
