導讀:興許全部程序員都有命名困難症,在考慮變量、常量、方法、類、文件等命名時,總會想方設法嘗試一些語義化的方式去實現。node
曾經有那麼一段時間,一些node初學的同窗遇到了一樣的問題:Hello World 跑不動!webpack
原文首發於我的博客:這事要從node node.js提及程序員
問題的起源很是簡單,當咱們在編寫一個入門程序時,就會迅速想起那句膾炙人口的語句:web
console.log('Hello World');
因而乎,順手保存爲node.js,緊接着嘗試以node node.js
來運行該示例程序。毫無疑問,在cmd環境下,會遇到以下的報錯:shell
(PS:實際上不管是Mac、Linux用戶,亦或是WIndows中使用Powershell或其餘終端環境的同窗都沒法與此問題完美邂逅)npm
此時此刻,心中一陣失落,竟然連入門的示例程序都沒法運行,不由一陣瞎想:是否該放棄node.js了?json
言歸正傳,細心的同窗會發現,報錯的源頭來自Windows Script Host
,下簡稱WSH
,咱們不難查到它是 Windows 操做系統腳本語言程序(script,即:腳本)的運行環境。windows
簡單分析一下node node.js
這條命令,咱們會很天然地認定爲:執行node.exe程序,參數爲node.js。學習
然而實際上,真正執行的程序卻變成WSH
,前面執行的命令node node.js
並無任何跟調起WSH
相關的邏輯,所以爲什麼調起了WSH
成爲了解謎的關鍵。ui
順蔓摸瓜,因爲WSH
正好是執行腳本的服務,而js偏偏又是腳本的一種,不妨假設node.js
這個腳本文件就是罪魁禍首。而後建立一個test.js
的副本,嘗試執行它:
根據試驗的結果不難猜出node node.js
命令實際執行了node.js
這個腳本文件,從而調起WSH
服務,進而出現上圖的報錯。
順水推舟可肯定node node.js
等價於.\node.js node.js
,即命令執行的文件完整的路徑爲:E:\test\node.js
。
(PS:各位看官切莫介懷''做爲路徑分隔符,畢竟在cmd下'/'擔任參數分隔符的要職)
先講講通用的說法,不管是 * nix 、OS/2 、DOS 亦或是 windows,其terminal均可以經過一個特殊的環境變量PATH
進行「補全」(關於環境變量的詳細內容本文不做介紹)。
接下來咱們經過ping命令先作簡要說明:
很明顯,在任何一臺正常的機器上,這條命令執行後都能獲得期待的結果。此時咱們能夠看到該cmd進程下的PATH
環境變量中包含C:\WINDOWS\system32
,經過對PATH
中的元素(文件夾路徑)便可將ping程序的路徑補全爲:C:\WINDOWS\system32\ping
。(在 * nix 系統下依然通用)
因爲windows的可執行的概念和 * nix 略有不一樣,所以在windows平臺下還須要對程序進行後綴名的補全。
其中在 * inx下,只需保證文件的結構符合規範,而且擁有可執行權限,就能夠執行;而在windows下,還須要考慮其後綴名及執行方式(其實是一種打開方式的策略)。
E:\test>echo %PATHEXT% .COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC;.PY;.PYW;.CPL
最終咱們補全的程序路徑爲:C:\WINDOWS\system32\ping.exe
,
針對於cmd環境,當前目錄也會做爲路徑補全的一部分,而且優先級最高。在當前目錄下,咱們建立一個ping.bat
的腳本,並填充如下內容:
@echo off :: 輸出完整的路徑和文件名及後綴 echo %~dpnx0
執行結果以下圖,原來的ping.exe
的動做明顯被覆蓋了。
咱們也額外地發現windows的默承認執行的後綴名包含.JS
,由此可推斷最初的那條node node.js
命令最終補全的程序路徑爲:E:\test\node.js
從2.2.4的結論中能顯而易見的推導出命令執行的程序爲node.js
腳本文件,那麼它爲何是經過WSH
去執行的呢?
答案其實很明顯,有個通俗易懂的概念,叫作打開方式,而windows的打開方式由assoc
和ftype
肯定。
嘗試性的跑一跑assoc
命令,發現其控制着後綴名與打開方式ftype
的關係。
assoc | findstr .js
運行結果:
.js=JSFile .json=VisualStudio.json.14.0 .jsonld=VisualStudio.jsonld.14.0 .jsx=VisualStudio.jsx.14.0 .jsxbin=JSXBINFile .jsxinc=JSXINCFile
不難看出.js
文件將會經過JSFile
這個打開方式去執行。
相似的,咱們也能夠運行一下ftype命令,其定義了可執行程序以及調用的參數。
ftype | findstr "JS"
運行結果:
JSEFile=C:\Windows\System32\WScript.exe "%1" %* JSFile=C:\Windows\System32\WScript.exe "%1" %* JSXFile="C:\Program Files (x86)\Adobe\Adobe Utilities - CS6\ExtendScript Toolkit CS6\ExtendScript Toolkit.exe" -run "%1"
其中最關鍵的信息爲JSFile=C:\Windows\System32\WScript.exe "%1" %*
,含義是經過WScript.exe
執行js腳本,並將原來的參數傳遞過去。
最終node node.js
等價於E:\test\node.js node.js
。
發動想象力吧,別再叫node.js
了~
是時候切換到 * inx 或者升級到powershell了~
若是不介意使用絕對路徑的話……
操做系統層面經過PATH
等環境變量進行資源定位的思路實際上也被普遍應用在各類場景下,下面也舉兩個常見的栗子說明一下。
CommonJS 規範中經過require
去加載模塊時,經過路徑補全的策略(詳情推薦閱讀《深刻淺出Node.js》),能夠省略模塊的路徑,後綴名,甚至連/index也能自動補全。
嘿,resolve中的extensions、alias等思路是否也一模一樣呢?
全文原創·此文爲隨走隨記,全文思惟略帶感情請勿拍磚。