標籤:

為什麼 Node.js 不給每一個.js文件以獨立的上下文來避免作用域被污染?

為什麼 Node.js 不給每一個.js文件以獨立的上下文來避免作用域被污染?


這……

實際上 node.js 使用的 commonjs 規範就是每個文件都是獨立的作用域啊!

至於說還是可以使用全局變數,那是JS語言本身的設計如此,但也可以通過 eslint 等代碼檢查工具來加以約束。

還有就是對象屬性或者原型之類可以被修改的問題,也是JS語言本身設計使然。通常編程時避免就可以了,如果一定要嚴格限制,可以用 Object.defineProperty 去禁止修改。


謝邀。

回答這個問題,要從 Node.js 對 CommonJS 的實現說起。上 Node 的源碼 https://github.com/nodejs/node/blob/master/lib/module.js#L556:

var wrapper = Module.wrap(content);

var compiledWrapper = vm.runInThisContext(wrapper, {
filename: filename,
lineOffset: 0,
displayErrors: true
});

// ...

var result = compiledWrapper.call(this.exports, this.exports, require, this,
filename, dirname);

關鍵代碼就這麼幾行。

content 可以認為是你的 .js 文件源碼,例如,我們簡單點:

console.log(module)

Module.wrap(content) 後:

(function (exports, require, module, __filename, __dirname) { console.log(module)
});

注意:上面是字元串操作。

vm.runInThisContext 後:

[Function]

將上面的字元串輸出變成了可執行的 JS 函數。實際上這個函數就是:

function(exports, require, module, __filename, __dirname) {
console.log(module)
});

最後執行這個函數,也就是 compiledWrapper.call(this.exports, this.exports, require, this, filename, dirname) 就是執行了這個模塊。

以上,就是 Node.js 對一個文本的 .js 模塊轉換成一個可使用的 JS 模塊的大致過程。

好了,回答題主問題,顯然,.js 文件的代碼都是包裹在一個函數里執行的,並不會產生作用域污染。

我們再追問一下,如果你不小心沒有寫var,定義了全局變數怎麼辦?,例如一不小心寫了這行代碼:

globalVar = 1

包裹之後變成了:

function(exports, require, module, __filename, __dirname) {
globalVar = 1
});

那這個 globalVar 是啥樣子?這其實是由 vm.runInThisContext 決定的,查看 Node.js 的文檔:

vm.runInThisContext() compiles code, runs it within the context of the current global and returns the result. Running code does not have access to local scope, but does have access to the current global object.

  1. vm.runInThisContext 使得包裹函數執行時無法影響本地作用域;
  2. 但 global 對象是可以訪問的,因此 globalVar = 1 等價於 global.globalVar = 1

如何避免這種對全局作用域的污染呢?

use strict;
globalVar = 1

添加 use strict;,禁止這樣意外創建全局變數,代碼執行時將拋出 globalVar 未定義的錯誤。

更準確地回答題主的問題:Node.js 模塊正常情況對作用域不會造成污染,意外創建全局變數是一種例外,可以採用嚴格模式來避免。


一開始我也覺得挺神奇的,不知道下面這個解釋算不算正解:

https://nodejs.org/api/modules.html#modules_the_module_wrapper


先問是不是?


餓了嗎面試題?


不知道就不要投簡歷了。==


全局變數是剛需啊


面試題?666,這是直接先給人下套哇


推薦閱讀:

為什麼nodejs不給每一個.js文件以獨立的上下文來避免作用域被污染?
nodejs中,zlib.gzip系列純cpu計算函數為什麼會有非同步版本?
es6 import from xx , 是怎麼實現找到 node_modules目錄下的?
Node.js伺服器端項目怎麼打包成單文件?

TAG:Nodejs |