Node.js 官方示例中的 ECMAScript 2015
第一個 Node.js 的伺服器應用
Node.js 官方提供的幫助文件中,提供了一個非常適合入門的示例程式碼。可以幫助我們快速瞭解 Node.js 的主要作用。
1. 建立 example.js 檔案,並將官方幫助文件提供的程式碼進行貼上:
const http = require('http');
const hostname = '127.0.0.1';
const port = 3000;
const server = http.createServer((req, res) => {
res.statusCode = 200;
res.setHeader('Content-Type', 'text/plain');
res.end('Hello World\n');
});
server.listen(port, hostname, () => {
console.log(`Server running at http://${hostname}:${port}/`);
});
2. 開啟命令列視窗,輸入如下 node 命令,執行 example.js:
node example.js
需要注意的是:上述命令必須在命令列模式下,進入到 example.js 檔案所在的目錄。
命令執行成功後,在命令列視窗會看到如下效果:
3. 開啟瀏覽器,在位址列輸入命令列視窗提供的地址,訪問 Node.js 服務:
http://127.0.0.1:3000
由於所有示例程式碼 Node.js 官方幫助文件提供了,所以執行演示的操作步驟非常簡單。但,我們不能忽略其中的一些細節。
仔細閱讀上述示例程式碼,我們會發現其中使用了很多有關 ECMAScript 2015 規範中的新內容。那接下來,就讓我們一一來了解一下吧。
const
、let
和var
的區別
首先,我們可以發現,在 Node.js 的官方幫助文件提供的示例程式碼中,大量地使用了 const
關鍵字。
const http = require('http');
const hostname = '127.0.0.1';
const port = 3000;
const server = http.createServer()
const
關鍵字是 ECMAScript 2015 規範中的新內容,是用來定義常量的。在 ECMAScript 2015 規範中還新增了 let
關鍵字,來替換原本的 var
關鍵字。
const
、let
和 var
關鍵字,都是用來在 JavaScript 中定義變數的。
1. 關於 JavaScript 的變數
變數是具有名字儲存資料資訊的容器。在程式碼中,使用變數名為值命名,需要遵守一定的規則。
值得注意的是:
- 在 JavaScript 程式碼中,必須先宣告一個變數,這個變數才能被使用。
JavaScript 中的變數是弱型別的,也稱之為鬆散型別的。所謂弱型別/鬆散型別就是可以用來儲存任何型別的資料。
var v = 100; v = "string";
2. 變數的宣告問題
1)重複宣告
使用 var
關鍵字重複宣告變數是合法且無害的。但是如果重複宣告並初始化的,這就表示重複宣告並初始化。由於 JavaScript 變數只能儲存一個資料,之前儲存的資料會被覆蓋。
var msg = "this is message";// 值為 this is message
var msg = 100;// 值為 100
2)遺漏宣告
直接讀取一個沒有宣告的變數的值,JavaScript 會報錯。
console.log(str);
上述示例程式碼,直接讀取了一個名為 str 的變數,但該變數並沒有宣告。所以,JavaScript 會報如下錯誤:
ReferenceError: str is not defined
- 為一個沒有宣告的變數初始化,是合法的,但並不推薦這樣使用。
3)宣告提前
JavaScript 變數的另一特別之處是,你可以引用稍後宣告的變數,而不會引發異常。這一概念稱為變數宣告提升。
console.log( msg );// 不會報錯,輸出 undefined
var msg = "this is message";// 定義全域性變數 msg
console.log( msg );// 輸出 this is message
上述程式碼中的第一行輸出不會報錯,而是輸出 undefined值。效果等同於如下述程式碼:
var msg;// 定義全域性變數 msg,但未初始化
console.log( msg );// 不會報錯,輸出 undefined
msg = "this is message";// 初始化全域性變數 msg
console.log( msg );// 輸出 this is message
3. let
是更完美的 var
1)let
擁有塊級作用域
在 ECMAScript 2015 規範釋出之前,JavaScript 只存在全域性作用域和函式作用域。
var v1 = 'this is global variable';
function fn(){
var v2 = 'this is function variable';
console.log('v1 in function scope: '+v1);
console.log('v2 in function scope: '+v2);
}
fn();// 在函式作用域中呼叫全域性變數和區域性變數
// 在全域性作用域中呼叫全域性變數和區域性變數
console.log('v1 in global scope: '+v1);
console.log('v2 in global scope: '+v2);
上述示例程式碼,執行時會報如下錯誤:
v1in function scope: this is global variable
v2in function scope: this is function variable
v1in global scope: this is global variable
scope.js:13
console.log('v2in global scope: '+v2);
^
ReferenceError: v2 is not defined
上述報錯的原因在於 v2
變數是被定義在 fn
函式中,是區域性變數,並不能在全域性作用域被呼叫。
接下來,我們再看另外一個示例:
for(var i=0;i<=9;i++){
console.log('use var define variable i in function scope: '+i);
}
console.log('use var define variable i in global scope: '+i);
上述示例程式碼的執行結果如下:
上述結果表明,在 for
迴圈語句中定義的 i
變數是一個全域性變數,因為在 ECMAScript 2015 之前,JavaScript 並不存在塊級作用域。
而將上述示例程式碼中,定義 i
變數的關鍵字 var
改成 let
,會有什麼變化呢?
for(let i=0;i<=9;i++){
console.log('use var define variable i in function scope: '+i);
}
console.log('use var define variable i in global scope: '+i);
上述修改過的示例程式碼,執行時會報如下錯誤:
use var define variable i in function scope: 0
use var define variable i in function scope: 1
use var define variable i in function scope: 2
use var define variable i in function scope: 3
use var define variable i in function scope: 4
use var define variable i in function scope: 5
use var define variable i in function scope: 6
use var define variable i in function scope: 7
use var define variable i in function scope: 8
use var define variable i in function scope: 9
/Users/king/node_and_mongoDB_in_action/01_first_node_demo/block_scope.js:10
console.log('use var define variable i in global scope: '+i);
^
ReferenceError: i is not defined
根據上述報錯資訊,我們可以知道在 for
迴圈外列印的 i
變數未定義。換句話講,就說明 i
變數只作用於 for
迴圈語句內部,而不是全域性作用域。
像上述示例中的 i
變數的作用域,我們就可以稱之為 塊級作用域。
2)let
不存在宣告提前
let
與 var
的第二個區別在於,使用 let
關鍵字宣告的變數,是不存在宣告提前的。
console.log( msg );
let msg = "this is message";
console.log( msg );
上述示例程式碼,執行是回報如下錯誤:
ReferenceError: msg is not defined
根據上述報錯資訊,表示使用 let
定義變數時,必須先宣告,後呼叫。
3) let
不允許重複宣告
let
與 var
的第三個區別在於,使用 let
關鍵字宣告的變數,是不允許重複宣告的。
let msg = "this is message";
console.log( msg );
let msg = "this is msg too";
console.log(msg);
上述示例程式碼,執行時會報如下錯誤:
SyntaxError: Identifier 'msg' has already been declared
根據上述報錯資訊,表示使用 let
定義變數時,只允許宣告一次,不能重複宣告。
4. const
定義常量
const宣告的變數只可以在宣告時賦值,不可隨意修改。
1)const
宣告時必須賦值
const theFairest;
上述示例程式碼,執行時會報如下錯誤:
SyntaxError: Missing initializer in const declaration
2) const
定義的值不能改變
// 定義常量MY_FAV並賦值7
const MY_FAV = 7;
// 在 Firefox 和 Chrome 這會失敗但不會報錯(在 Safari這個賦值會成功)
MY_FAV = 20;
console.log(MY_FAV); // 輸出 7
const MY_FAV = 20; // 嘗試重新宣告會報錯
var MY_FAV = 20;// MY_FAV 保留給上面的常量,這個操作會失敗
console.log(MY_FAV);// MY_FAV 依舊為7
上述示例程式碼,執行時會報如下錯誤:
SyntaxError: Identifier 'MY_FAV' has already been declared
箭頭函式
在 Node.js 的官方幫助文件提供的示例程式碼中,我們可以看到如下形式的函式:
http.createServer((req, res) => {
res.statusCode = 200;
res.setHeader('Content-Type', 'text/plain');
res.end('Hello World\n');
});
server.listen(port, hostname, () => {
console.log(`Server running at http://${hostname}:${port}/`);
});
上述示例中的函式形式,看起來很怪異,我們將其進行改寫:
const server = http.createServer(function(req, res){
res.statusCode = 200;
res.setHeader('Content-Type', 'text/plain');
res.end('Hello World\n');
});
server.listen(port, hostname, function(){
console.log(`Server running at http://${hostname}:${port}/`);
});
進行改寫後的程式碼,是否更熟悉一些呢。那 Node.js 官方幫助文件中提供的示例程式碼裡使用的又是什麼呢?
1. 定義無參的箭頭函式
在 ECMAScript 5 之前,我們定義一個無參函式是這樣的:
var fn = function(){
return 'this is function';
}
而在 ECMAScript 2015 之後,我們可以利用箭頭函式定義是這樣的:
var fn = () => 'this is function';
上述兩個函式的定義是等價的。
2. 定義帶參的箭頭函式
如果想要定義帶有引數的箭頭函式,可以如下方式:
var fn = v => v;
上述程式碼等同於如下:
var fn = function(v){
return v;
}
如果定義帶有多個引數的箭頭函式,可以將引數通過圓括號進行包裹。
var sum = (num1, num2) => num1 + num2;
上述程式碼等同於如下:
var sum = function(num1, num2) {
return num1 + num2;
}
3. 箭頭函式體包含多條語句
上述示例程式碼中,我們只在箭頭函式中定義了一條語句。那想要定義多條語句的話,可以將所有函式體內的語句通過大括號進行包裹。
var sum = (num1, num2) => {
if(num1 < num2){
return num1;
}else{
return num2;
}
}
上述程式碼等同於如下:
var sum = function(num1, num2) {
if(num1 < num2){
return num1;
}else{
return num2;
}
}
大括號會被解析為程式碼塊。如果箭頭函式想要返回的是複雜資料(例如物件),需要使用圓括號進行包裹。
var me = () => ({ name: "longestory" });
上述程式碼等同於如下:
var me = function() {
return { name: "longestory" };
}
4. 箭頭函式的作用
通過上述內容,我們已經基本掌握了箭頭函式的用法。那箭頭函式究竟會有什麼作用呢?我們再回過頭來看看 Node.js 官方幫助文件的示例程式碼。
// ECMAScript 5 中的寫法
http.createServer(function(req, res){
res.statusCode = 200;
res.setHeader('Content-Type', 'text/plain');
res.end('Hello World\n');
});
上述示例程式碼中,我們可以知道,通過 http
物件呼叫了 createServer
方法的同時向該方法傳遞了一個回撥函式。
// ECMAScript 2015 中的寫法
http.createServer((req, res) => {
res.statusCode = 200;
res.setHeader('Content-Type', 'text/plain');
res.end('Hello World\n');
});
所以,箭頭函式的主要用法之一,就是用來簡化回撥函式的使用。
模板字串
在 Node.js 的官方幫助文件提供的示例程式碼中,我們還看到一行比較特殊的程式碼。
console.log(`Server running at http://${hostname}:${port}/`);
上述示例程式碼如果被改寫成這樣,相信你會更熟悉。
console.log('Server running at http://'+hostname+':'+port+'/');
實際上,在上述程式碼中,其實是使用了 JavaScript 的字串拼串。而 Node.js 的官方幫助文件中的示例程式碼,則使用 ECMAScript 2015 規範中的 模板字串。
1. 模板字串的基本使用
模板字串(template string)是增強版的字串,用反引號(`)標識。
console.log(`this is a string.`);
上述示例程式碼的輸出結果如下:
this is a string.
你會發現上述示例程式碼的輸出結果與 ECMAScript 5 中的普通字串並沒有任何區別。
console.log('this is a string.');
但,如果我們想要輸出的字串很複雜,或者是多行的。那 ECMAScript 5 中的寫法應該是這樣的:
$('#list').html(
'<ul>'+
'<li>first</li>'+
'<li>second</li>'+
'</ul>'
);
而使用 ECMAScript 2015 規範中的模板字串,我們就可以寫成這樣:
$('#list').html(`
<ul>
<li>first</li>
<li>second</li>
</ul>
`);
2. 模板字串中使用變數
如果輸出的是一些文字加上變數的內容的話,在 ECMAScript 5 中的寫法是這樣的:
const hostname = '127.0.0.1';
const port = 3000;
console.log('Server running at http://'+hostname+':'+port+'/');
也就是說,我們在實際開發中,需要大量的字串拼寫工作。這樣做的問題在於:
- 工作量巨大
- 比較容易出錯
而 ECMAScript 2015 規範中的模板字串,則允許嵌入變數。只需要將需要嵌入的變數通過 ${}
進行包裹即可。
const hostname = '127.0.0.1';
const port = 3000;
console.log(`Server running at http://${hostname}:${port}/`);
在模板字串中,甚至可以嵌入函式的呼叫。
function fn(){
return 'Hello';
}
console.log(`${fn()} World`);
上述示例程式碼執行的結果如下:
Hello World
3. 模板字串的注意事項
當然,模板字串在使用過程中,也需要注意一些問題。
如果模板字串中嵌入的變數沒有宣告,則會報錯。
console.log(`Server running at http://${hostname}/`);
上述示例程式碼,執行後會報如下錯誤:
ReferenceError: hostname is not defined
相關文章
- ECMAScript® 2015 Language Specification
- ECMAScript 2015正式釋出
- 快來使用ECMAScript 2015吧
- 水晶報表官方示例
- [譯] 瀏覽器中的 ECMAScript 模組瀏覽器
- Struts官方示例學習-Wildcard_method示例
- ECMAScript 6中除類之外的OOP新特性OOP
- Node.js 事件迴圈-比官方更全面Node.js事件
- Halcon斑點分析官方示例講解
- Go 官方包函式學習及示例Go函式
- Node.js中的BufferNode.js
- node.js中的流Node.js
- ECMAScript——(二)
- 探索 ECMAScript 2023 中的新陣列方法陣列
- [譯] ECMAScript 的 Observables 提案
- ? React-Native 官方示例演示 ( ios & android)ReactiOSAndroid
- ECMAScript中的Number Type與 IEEE 754-2008
- node.js中的流(stream)Node.js
- Node.js 中的 Event loopNode.jsOOP
- Sentry-JS-SDK-Browser 官方示例最佳實踐JS
- 【GoLang】GoLang 錯誤處理 -- 官方推薦方式 示例Golang
- Frida官方手冊 - Android上示例一則Android
- Google官方MVP示例程式碼閱讀筆記GoMVP筆記
- Python中Mock的示例PythonMock
- xrender中的FormRender使用示例ORM
- 2015阿里百川官方手冊阿里
- JavaScript 26 週歲生日!Node.js 官方發推特慶祝JavaScriptNode.js
- 【譯】Node.js中的Event LoopNode.jsOOP
- Node.js 中 Stream API 的使用Node.jsAPI
- 2.9.6 資料庫中的示例資料庫
- Java中的WeakHashMap與類示例JavaHashMap
- Eta中的Apache Flink示例Apache
- JavaScript中回撥的示例理解JavaScript
- ECMAScript 6:更好的 Unicode 支援Unicode
- ECMAscript一些方法的使用
- 玩轉ECMAScript 6 ~
- ECMAScript 6 掃盲
- ECMAScript 6教程 (三)