ECMAScript 6 都已經正式釋出兩年了,才來從 ECMAScript 5 開始?其實也是因為這樣,還有那樣的原因,我有必要重新看一下 JavaScript 的東西,只是看有點無聊,想說就乾脆來改版好了… XD
不少長青(Even-green)瀏覽器在 ES6 的支援度上已經不錯了,然而為了相容性,不少程式庫或既有應用程式,都還不是 ECMAScript 6 寫的,那麼至少,從 ECMAScript 5 嚴格模式比較好,更舊的寫法我就不再提了。
如果打算把應用程式從舊舊的 JavaScript 昇至 ECMAScript 6,先想辦法整理程式碼,使之能在 ECMAScript 5 嚴格模式下存活,會是比較漸進的作法;就算想用 ECMAScript 6 重寫應用程式,然而基於相容性,使用了工具將 ECMAScript 6 轉換為舊版的 JavaScript,總是有時會需要看懂轉換出來的程式碼吧!
因此,接下來會先以〈JavaScript 語言核心〉為基礎進行修改,忽略那些嚴格模式下無法使用的語法元素,在 ECMAScript 5 重新整理完過後,希望能開始聊聊 ECMAScript 6,然後將〈JavaScript 本質部份〉中,瀏覽器部份的文件也用 ECMAScript 6 更新一下,並將舊版 IE 的說明剔除 … 呃… 這會是一條漫長的路(想到就蠻累的,總之慢慢來吧! … XD)。
那麼,就語言的部份,還是使用 Node.js 來作為示範平臺吧!(雖然 JDK9 附的 jjs
也支援不少 ES6 特性了,不過不知道支援到什麼程度就是了)就寫這篇文件的時間點上,我使用的是 8.9.1 LTS 的 Windows 版本。
C:\workspace>node -v
v8.9.1
只輸入 node
會進入指令互動環境,按下 Ctrl+D 可以離開,如果要將程式碼寫在 .js 裏頭再執行,例如編輯一個 helloworld.js:
console.log('Hello, World');
然後執行 node helloworld.js
就可以執行程式:
C:\workspace>node helloworld.js
Hello, World
如果需要在執行時給定命令列引數的話,可以使用 process.argv
,這是一個陣列(Array
實例),索引 0 是 'node'
指令名稱,索引 1 是你的 .js 檔案路徑,如果有指定引數的話,這些引數會是從索引 2 開始儲存。例如若你的 helloworld.js 是:
process.argv.forEach(function(arg, index) {
console.log(arg + ', ' + index);
});
那麼指定引數時,就會有以下的執行結果:
C:\workspace>node helloworld.js arg1 arg2
C:\Program Files\nodejs\node.exe, 0
C:\workspace\helloworld.js, 1
arg1, 2
arg2, 3
你發現了,我使用的是 Windows 版本上的,就學習語言而言,Windows 版本基本上應該是沒問題。通常,我不太需要指令名稱與檔案路徑,因此,可以只擷取之後索引 1 之後的引數:
var args = process.argv.slice(2);
console.log('Hello, ' + args[0]);
這樣的話,就可以透過 args
索引 0 開始來取得 .js 檔案名稱之後供給的命令列引數了:
C:\workspace>node helloworld.js Justin
Hello, Justin
ECMAScript 5 的嚴格模式(strict mode),這只要在你想要的程式碼範疇中,加入一段 use strict
字串,如果有支援嚴格模式的環境就會採納,沒有支援的環境,只是當作一個平凡的字串罷了。
例如,在 ES5 的嚴格模式下,不允許對未使用 var
宣告的變數指定值:
'use strict';
x = 10;
console.log(x);
使用 Node.js 的話,執行以上 .js 檔案,將會發生錯誤:
C:\workspace>node helloworld.js
C:\workspace\helloworld.js:4
x = 10;
^
ReferenceError: x is not defined
at Object.<anonymous> (C:\workspace\helloworld.js:4:7)
at Module._compile (module.js:635:30)
at Object.Module._extensions..js (module.js:646:10)
at Module.load (module.js:554:32)
at tryModuleLoad (module.js:497:12)
at Function.Module._load (module.js:489:3)
at Function.Module.runMain (module.js:676:10)
at startup (bootstrap_node.js:187:16)
at bootstrap_node.js:608:3
也可以在使用 node
指令時,加上 --use_strict
,例如:
C:\workspace>node --use_strict
> x = 10;
ReferenceError: x is not defined
at repl:1:3
at ContextifyScript.Script.runInThisContext (vm.js:50:33)
at REPLServer.defaultEval (repl.js:240:29)
at bound (domain.js:301:14)
at REPLServer.runBound [as eval] (domain.js:314:12)
at REPLServer.onLine (repl.js:441:10)
at emitOne (events.js:121:20)
at REPLServer.emit (events.js:211:7)
at REPLServer.Interface._onLine (readline.js:282:10)
at REPLServer.Interface._line (readline.js:631:8)
>
必須先聲明的是,這系列不是 JavaScript/ECMAScript 語言入門,我只會寫些語言中我覺得有興趣的特性,因此,雖然從 ES7 開始,ECMAScript 打算採頻繁的方式,持續每年釋出新版本,內容包含當年已完成的新特性就好,不過,我目前的規劃是不打算跟著這樣 ES7、ES8 寫下去,而這系列也不會是 Node.js 的介紹,方才一連串的簡介,只是為了後續介紹語言核心時的必要準備。