导读:兴许全部程序员都有命名困难症,在考虑变量、常量、方法、类、文件等命名时,总会想方设法尝试一些语义化的方式去实现。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等思路是否也一模一样呢?
全文原创·此文为随走随记,全文思惟略带感情请勿拍砖。