SlideShare a Scribd company logo
JavaScript 與 Node.js
Peter 易弼仁
2
└ JavaScript
└ 變數
└ 陣列
└ 函式
└ 物件
└ 條件與迴圈
└ Node.js
└ 生態系
└ 基礎練習
└ Callback
└ 建構式
└ 繼承
└ 模組化
└ 事件發射器
課程綱要
└ 第三方模組
└ npm
└ lodash
└ 伺服器
└ http server
└ socket.io
└ 即時聊天室
投影片位置:SlideShare – ntut js and node
3
└ 確認系統已經安裝好 Node.js
開始之前
安裝教學:https://nodejs.org/en/
JavaScript
5
JavaScript
和 Java 是不同的語言
不是只能用在前端網頁上
適合物件導向、函式導向設計
高階、動態、無型別的直譯語言
6
變數
規則
└ 第一個字元不可是數字
└ 只能是字母、底線和錢字號
└ 不可為關鍵字
└ 如 If、for、this 等等
└ 區分大小寫
└ myname、MYNAME 為不同變數
└ 慣例使用小駝峰命名
└ 如 myName、mySchool
└ 無型別
└ 以逗號分隔多個變數
關鍵字
└ var
└ let
└ 只有在 let 宣告的範疇中有效
└ 沒有變數提升 (hoisting)
└ const
└ 用來宣告常數
└ 宣告時需指定值
└ 沒有變數提升 (hoisting)
// 正確
var myName;
var _func;
var $i;
// 錯誤
var 01x;
var @test;
var #dash;
var a = 10,
b = 'test';
7
變數範疇
一個變數的範疇 (scope) 是指程式碼中該變數有定義的區域
└ JavaScript 有兩種變數範疇:全域變數和區域變數
└ 區域變數的優先序比同名稱的全域變數高
└ 使用 var 在函式內宣告的變數為區域變數
└ 使用 let 在函式、for 區塊、if 區塊、或純區塊內宣告的變數為區域變數
var scope = 'global';
function checkScope() {
var scope = 'local’;
console.log(scope); // local
}
checkScope();
console.log(scope); // global
let x = 1;
if (true) {
let x = 2;
console.log(x); // 2
}
console.log(x); // 1
var x = 1;
if (true) {
var x = 2;
console.log(x); // 2
}
console.log(x); // 2
8
變數提升
console.log(a);
var a = 10;
console.log(a);
undefined
10
變數宣告會被提升 (hoisting) 到該範疇的最上方
└ 變數初值設定的位置不變
└ let 和 const 沒有變數提升
console.log(a);
let a = 10;
ReferenceError: a is not defined
console.log(a);
const a = 10;
ReferenceError: a is not defined
9
物件是一堆名稱與值的組合
└ 資料與行為的封裝
└ 擬人化、擬物化
└ 物件擁有紀錄資料與行為的屬性
└ 每個屬性就是一對名稱與值
└ 屬性值可以是任意 JavaScript 的值
└ 若值為函式,我們稱它為物件的方法 (method)
└ JavaScript 中所有東西都是物件
└ 不論是數字、字串、陣列、函式等等
物件
var person = {};
person.name = 'Jack';
person['age'] = 26;
var person = {
name: 'Jack',
age: 26,
friends: ['Hedy', 'Peter', 'Simen'],
parents: {
father: 'Eric’,
mother: 'Ann'
},
speak: function (text) {
console.log(text);
}
};
var person = {
name: 'Jack',
age: 26
};
10
一個陣列是一組值的有序群集
└ 其中的值稱為元素 (element)
└ 元素的位置稱為索引 (index)
└ 第一個元素的索引為 0
└ 陣列中不同元素可以是不同型別
└ 只支援一維陣列
└ 但可以在陣列放入陣列來實現二維陣列
└ 每個陣列都有 length (長度) 屬性
陣列
var num = [1, 3, 7, 9, 21, 43];
var name = ['Simen', 'Hedy', 'Peter'];
console.log(num.length); // 6
console.log(name.length); // 3
var array = ['Hello', ' World', '!'];
console.log(array[0] + array[1] + array[2]);
array[1] = ' JavaScript';
console.log(array[0] + array[1] + array[2]);
Hello World!
Hello JavaScript!
var array = [[‘x1’, ‘x2’], [‘y1’, ‘y2’]];
console.log(array[0][1]); // x2
11
函式是一段程式碼,可被多次執行
└ 使用關鍵字 function 來定義
└ 未定義名稱的函式為匿名函式
└ 函式有兩種定義的方式
└ 函式宣告式與函式運算式
└ 函式宣告會被提升 (hoisted)
└ 函式也是一個物件
函式
function add (x, y) {
return x + y;
}
var sum = add(2, 3);
console.log(sum);
var greet = function (name) {
console.log('Hello ' + name + '!');
}
greet('Simen');
function greet (name) {
console.log('Hello ' + name + '!');
}
greet('Simen');
(function (name) {
console.log('Hello ' + name + '!’);
}('Simen'));
條件與迴圈
13
If 是條件判斷最基本的語法
└ 條件必須是 Boolean 值或運算式
└ 若是其他值,則會被自動轉型為 Boolean 值
└ 用 else if 來判斷多個條件
└ else if 數量沒有限制
└ 用 else 處理條件不符合的情況
└ 判斷式是由上到下循序執行
└ 當一個條件成立時,後面的條件不再繼續判斷
If
if (條件) {
條件為 true 時執行此程式
}
if (條件1) {
條件1為 true 時執行此程式
} else if (條件2) {
條件1不為 true,但條件2為 true 時執行此程式
} else {
條件皆不為 true 時執行此程式
}
function description(height) {
if (height < 165) {
console.log('矮');
} else if (height >= 165 && height < 175) {
console.log('平均');
} else {
console.log('高');
}
}
description(173); // '平均'
14
判斷不同情況下執行不同的程式碼
└ 查對條件與標籤
└ 用 break 跳出 switch
└ 可以用 return 取代
└ 用 default 定義沒有相符的標籤時執
行的程式碼
switch
switch(條件) {
case 標籤:
如果條件 === 標籤時執行此程式
break;
default:
若沒有與條件相符的標籤時執行此程式
}
function isTodayWeekend() {
var day = new Date().getDay();
switch(day) {
case 6:
console.log('Today is Saturday’);
break;
case 0:
console.log('Today is Sunday');
break;
default:
console.log('Today is not weekend');
}
isTodayWeekend(); // 'Today is not weekend'
15
while 是迴圈最基本的語法
└ 可用來創建無窮迴圈
└ do / while 在迴圈底部才判斷條件
└ 也就是說本體程式碼至少會被執行一次
└ do 迴圈結尾一定要分號
while
while (條件) {
條件為 true 時執行程式,並重複迴圈。
}
var a = 0;
while (a < 5) {
console.log(a);
a++; // a = a + 1
}
do {
執行此程式後判斷條件,若條件為 true 時重複迴圈。
} while (條件);
var b = 0;
do {
console.log(b);
b++;
} while (b < 5);
16
for 迴圈經常比 while 來得便利
└ 簡化某種共通形式的迴圈
└ 初始化、條件判斷、更新
└ 任一個都可以省略
└ 但兩個分號不可省略
for
for (初始化; 條件判斷; 更新) {
條件為 true 時執行程式,並重複迴圈
}
var sum;
for (var i = 0; i < 5; i ++) {
sum = sum + i;
}
console.log(sum); // 10
Node.js
18
Node.js 將 JavaScript 推向另一個境界!
└ Real-time Web Server
└ 單執行緒
└ 事件驅動架構
└ 非同步式 I/O
Node.js
Node.js Core
Node.js Bindings (C++)
Google V8 (C++) libuv
JavaScript Engine Cross-platform Async I/O
19
└ 套件管理系統與蓬勃發展的生態系
Node.js 生態系
Node.js Native Modules 3rd-party Modules
http stream events
buffer process …
express lodash q
async mocha …
Our Node.js Application
http … express lodash async …
npm install <module>
npm is not only a node package manager!
20
基礎練習
└ (01) 用 console.log() 印出 Hello World!
└ (02) 宣告一個變數 x,並其為字串 “Hello World!”,然後印出 x
條件與迴圈
└ (03) 使用 while 迴圈印出 10 次 Hello World!
└ (04) 使用 for 迴圈印出 10 次 Hello World!
└ (05) 在 for 迴圈中,當執行第 i 次且 i 是奇數才印出 “Hello World!” (使用 if )
從 Hello World 開始
3 mins
5 mins
21
你可以偷看一下
console.log('Hello World!');
var x = 'Hello World!';
console.log(x);
for (var i = 0; i < 10; i++) {
console.log('Hello World!');
}
var i = 0;
while (i < 10) {
console.log('Hello World!');
i++;
}
for (var i = 0; i < 10; i++) {
if ((i%2) !== 0)
console.log('Hello World!');
}
01
02
04
03
05
22
函式
└ (06) 將打印 Hello World! 包裝成一支函式 hello(),然後呼叫它
物件
└ (07) 建立一個代表人 (person) 物件,該物件要包含有 name、gender 和 age 屬性,
並且印出 person 物件與其中的屬性 name
└ (08) 呈上,在人的物件中,加入方法 speak(),這個方法會傳入一個參數 text,並且
它會印出傳入的參數
來練習函式和物件
2 mins
5 mins
23
你可以偷看一下
function hello() {
console.log('Hello World!');
}
hello();
06
var person = {
name: 'John',
gender: 'man',
age: 20
};
console.log(person);
console.log(person.name);
07
var person = {
name: 'John',
gender: 'man',
age: 20,
speak: function (text) {
console.log(text);
}
};
person.speak('Hi Hi~');
08
24
Callback
└ 回呼函式、回調函式
└ 當呼叫一個函式 a 時,給他另一個函式 b;
當某種條件成立時 ,就回過頭呼叫函式 b
練習一下
└ (09) 寫一支函式 repeatHello(times, callback),然後試著呼叫它來執行 10 次 hello();這裡的
callback 應該放誰呢?
什麼是 Callback
function a (x, y, callback) {
// ... do something
callback();
}
function b () {
// I am a function
}
a('hello', 88, b);
4 mins
25
你可以偷看一下
function hello() {
console.log('Hello World!');
}
function repeatHello(times, callback) {
for (var i = 0; i < times; i++) {
callback();
}
}
repeatHello(10, hello);
09
26
建構式
└ 建立類別
└ 根據類別建立新的物件實例
└ 與 new 運算子一起使用
└ 名稱字首大寫
└ 原型:prototype
└ JavaScript 中所有物件都具有 prototype
└ Object.prototype、Array.prototype、
Function.prototype
└ 每 new 一個新的物件實例時,所有屬性都會被
new 一份出來,但原型就不會,因為是「繼承」
的概念!
建構式
Class: Person
Name
Age
Gender
Object: Peter
Name: Peter
Age: 24
Gender: men
Object: Simen
Name: Simen
Age: 36
Gender: men
Object: Hedy
Name: Hedy
Age: 23
Gender: women
function Person(name) {
this.name = name;
}
Person.prototype.hello = function () {};
var john = new Person('John');
27
this
└ 會指向調用函數的物件實例
└ 在不同的場合使用它所指向的對象會不同
└ 一般函式:根據是否為嚴格模式有所差異,在稀鬆模式中
this 會參考到全域物件;在嚴格模式中 this 為 undefined
└ 建構式:this 參考到實例
└ 方法:this 參考到調用該方法的物件
this
var savedThis;
function Constr() {
savedThis = this;
}
var inst = new Constr();
console.log(savedThis === inst);
// true
var obj = {
method: function () {
console.log(this === obj);
// true
}
}
obj.method();
'use strict';
console.log(this);
// undefined
1
2
3
1
2
3
28
建構式
└ (10) 建立一個 Person 建構式
└ 屬性:name, age, gender
└ 方法:hello
└ hello 方法會印出 “Hello, I am xxx.”
└ xxx 為新增實例時傳入的名字
└ 新增一個 Person 的實例
練習一下
5 mins function Person(name, gender, age) {
this.name = name;
this.gender = gender;
this.age = age;
}
Person.prototype.hello = function () {
console.log("Hello, I am " + this.name + ".");
};
var john = new Person('John', 'man', 20);
console.log(john);
john.hello();
10
29
建構式
└ (11) 建立一個 Student 的建構式
└ 屬性:name, age, gender, school
└ 方法:hello, greet
└ greet 方法會印出 “Hello, I am xxx.” 和
“A student from ooo”
└ xxx 為新增實例時傳入的名字
└ ooo 為新增實例時傳入的學校
└ 新增一個 Student 的實例
練習一下
function Student(name, gender, age, school) {
this.name = name;
this.gender = gender;
this.age = age;
this.school = school;
}
Student.prototype.hello = function () {
console.log("Hello, I am " + this.name + ".");
};
Student.prototype.greet = function () {
console.log("Hello, I am " + this.name + “.");
console.log("A student from " + this.school + “.");
};
var john = new Student('John', 'man', 20, 'NTU');
console.log(john);
john.hello();
john.greet();
115 mins
30
繼承另一個物件的屬性與方法
└ 實現物件原型繼承的函式 util.inherits()
└ util.inherits(A, B) 是把 B.prototype 複製到 A 身上
└ 使用 call() 繼承屬性
└ 讓父建構式用子建構式的 this 來執行初始化
└ call() 是 Function.prototype 中的方法
練習一下
└ (12) 使用 util.inherits() 讓 Student 繼承自 Person
└ 屬性:school
└ 方法:greet
重寫好麻煩:繼承
8 mins
function Student(name, school) {
Person.call(this, name);
this.school = school;
}
util.inherits(Student, Person);
var john = new Student('John', 'NTUT');
function Person(name) {
this.name = name;
}
Person.prototype.hello = function () {};
31
你可以偷看一下
var util = require('util');
// Class: Person
function Person(name, gender, age) {
this.name = name;
this.gender = gender;
this.age = age;
}
Person.prototype.hello = function () {
console.log("Hello, I am " + this.name + ".");
};
// Class: Student
function Student(name, gender, age, school) {
Person.call(this, name, gender, age);
this.school = school;
}
util.inherits(Student, Person);
Student.prototype.greet = function () {
console.log("Hello, I am " + this.name + “.");
console.log("A student from " + this.school);
};
var john = new Student('John', 'man', 20, 'NTUT');
john.hello();
john.greet();
12


這個程式寫完後,請試著單獨拿掉 ,執行看看結果如何。然後,
試著單獨拿掉  再看看結果如何。如果有異狀,想想看為什麼?
引用 Node.js 原生模組 util
32
模組是 Node.js 的重要支柱
└ 將程式拆分、封裝
└ 第三方模組
└ require() 載入模組
└ module.exports 公開模組介面
└ module.exports 初始值是一個物件
└ exports 也可以公開模組介面,但要注意他是
module.exports 初始值的參考
練習一下
└ (13) 讓 Person 成為一個模組,讓 Student 引用
模組系統
5 mins
var name = 'peter'
function hello() {
console.log("Hello, I am " + name + ".");
}
module.exports = hello;
var hello = require(‘./hello’);
hello();
var name = 'peter'
exports.hello = function () {
console.log("Hello, I am " + name + ".");
}
var obj = require(‘./hello’);
obj.hello();
33
你可以偷看一下
// Class: Person
function Person(name, gender, age) {
this.name = name;
this.gender = gender;
this.age = age;
}
Person.prototype.hello = function () {
console.log("Hello, I am " + this.name + ".");
};
module.exports = Person;
var util = require('util');
var Person = require('./13_Person');
// Class: Student
function Student(name, gender, age, school) {
// 略
}
util.inherits(Student, Person);
Student.prototype.greet = function () {
// 略
};
var john = new Student('John', 'man', 20, 'NTU’);
console.log(john);
john.hello();
john.greet();
13
匯出 Person 建構子
匯入 Person 建構子
34
event 是 Node.js 最重要的模組
└ Node.js 是事件驅動式,而 events 物件提供唯一的介面
└ events 只提供了一個建構式:EventEmitter
└ 大多時候我們會讓物件繼承它,而不是直接使用
└ EventEmitter 提供事件發射與事件監聽器功能
└ .emit() 發射事件
└ .on() 新增事件監聽器
練習一下
└ (14) 新增一個 NewEmitter 建構式,並讓該建構式繼承事件發射器
└ 新增一個 newEmitter 實例
└ 試著每 3 秒引發事件 'show_me',然後在監聽器中印出 Hello World!
事件發射器
5 mins
emitter.on('greet', function(name) {
console.log('Hello ' + name + ".");
});
emitter.emit('greet’, 'peter’);
35
你可以偷看一下
var util = require('util');
var EventEmitter = require('events').EventEmitter;
function NewEmitter() {}
util.inherits(NewEmitter, EventEmitter);
var newEmitter = new NewEmitter();
newEmitter.on('show_me', function() {
console.log('Hello World!');
});
setInterval(function () {
newEmitter.emit('show_me');
}, 3000);
16
第三方模組
37
Git 是一套分散式版本管理系統
└ 支援本地操作、備份容易
└ 功能強大且具彈性的分支與合併
Github 是軟體原始碼代管服務
└ 世界上最大的程式碼存放網站和開源社群
└ 個人和組織建立和存取保管中的程式碼
└ 共同軟體開發功能
└ 完整的 Git 版控支援
開源無所不在
GitHub
38
Node.js 強大靈活的套件管理員
└ 目前已有上萬個協力廠商模組
└ 一行指令就能安裝別人寫好的模組
└ 安裝指令:npm install <package name>
└ 模組被安裝到 node_modules 目錄
└ 安裝前 npm 會先檢查目錄中是否已存在指定模組
└ 安裝 Node.js 會連帶安裝 npm
Node Package Manager
npm
39
└ npm init
└ 初始化專案資訊
└ 產生 package.json
└ npm install <package name>
└ 安裝指定套件到 node_module 目錄
└ npm 會先檢查當下的 node_module 目錄
└ npm install <package name> -save
└ 安裝指定套件到 node_module 目錄
└ 並將該模組與其版本寫入 package.json
└ npm install <package name> -g
└ 安裝指定套件到全域目錄
npm 常用指令
└ npm install
└ 根據 package.json 安裝專案所需的相依套件
└ npm update <package name>
└ 更新專案中的指定模組
└ npm update
└ 更新專案中的所有模組
40
package.json 定義模組的相依套件及資訊
└ npm install 指令根據它自動下載相依模組
└ 欄位簡述
└ name:模組名稱
└ version:模組版本號
└ decription:模組的簡短描述
└ main:程式進入點
└ script:腳本指令
└ dependencies:模組所依賴的第三方模組清單
└ devDependencies:模組在開發階段所依賴的第三方模組清單
└ keywords:模組關鍵字
└ author:模組作者
└ license:模組版權
package.json
{
"name": "npm-example",
"version": "0.0.1",
"decription": "Experiment",
"main": "index.js",
"dependencies": {
"request": "0.1.0"
},
"devDependencies": {
"mocha": "2.1.0"
},
"script": {
"start": "node index.js"
},
"keywords": [
"example"
],
"author": "PeterEB",
"license": "MIT"
}
41
一個 JavaScript 實用的工具模組
└ 提供像 Function、Array、Object 原生物件的方法
└ 讓程式碼更佳的簡潔及好維護
└ 效能比原生物件的方法好
└ Underscore 的強化版
lodash
文檔
var _ = require('lodash');
_.defaults({ 'a': 1 }, { 'a': 3, 'b': 2 });
// { 'a': 1, 'b': 2 }
_.partition([1, 2, 3, 4], n => n % 2);
// [[1, 3], [2, 4]]
_.toLower('PETER');
// peter
42
練習一下
└ (17) 新增一個專案,並安裝 lodash
└ (18) 建立一個陣列中放入數字 1 – 10,接著找出數字 5 的索引 (index)
└ _.indexOf(array, value, [fromIndex = 0])
└ (19) 建立一個 person 物件,接著將各個屬性名稱與屬性值分別印出
└ 包含 name、gender、age 屬性
└ 分別印出 “name: xxx”、“gender: xxx”、“age: xxx”
└ _.forEach(collection, iteratee)
└ iteratee: function (value, key)
練習一下
43
你可以偷看一下
$ npm init
17
example$ npm install lodash
var _ = require('lodash');
var num = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
console.log(_.indexOf(num, 5));
18
var _ = require('lodash');
var person = {
name: 'John',
gender: 'man',
age: 26
};
_.forEach(person, function(value, key) {
console.log(key + ': ' + value);
});
19
伺服器
45
Node.js 原生的 HTTP 模組
└ 建立 HTTP 伺服器
└ 接收請求、回應請求
└ res.writeHead()、res.write()、res.end()
└ 發送請求
http
var http = require("http");
http.createServer(function(req, res) {
res.writeHead(200, {"Content-Type": "text/html"});
res.write("<h1>Node.js</h1>");
res.end("<p>Hello World! I'm built by Node.js</p>");
}).listen(3000);
console.log("HTTP Server is listening at port 3000."); 文檔
46
練習一下
└ (20) 建立一個 HTTP 伺服器,監聽連接埠 80
└ 瀏覽器訪問時會回傳 Hello World!
└ http.createServer(handler(req, res))
└ res.end()
練習一下
var http = require("http");
http.createServer(function(req, res) {
res.end(“Hello World!");
}).listen(80);
console.log("HTTP Server is listening at port 80.");
20
47
讓客戶端與伺服器進行互動通訊的技術
└ 在單個 TCP 連線上進行全雙工通訊
└ HTML5 定義了 WebSocket 協定
└ 使客戶端與伺服器間資料交換變得更加簡單
└ 客戶端與伺服器只須完成一次交握,便能建立持續性連線
└ 交握採用 HTTP 協定,並且只需再交握時攜帶狀態資訊,之後的通訊可省略部分狀態資訊
└ 伺服器能主動向用戶推播資料
└ 不需要對資料更改進行輪詢
└ 使客戶端反應更即時
└ 可用來建立 Real-time Web
WebSockets
48
Socket.io 是 WebSockets 更高一層的抽象層模組
└ 提供易用的伺服器端與客戶端模組
└ socket.io 與 socket.io-client
└ 支援 Flash、XHR、JSONP 等
└ 在某些瀏覽器不支援 WebSocket 的狀況下,則會自動改用其他的方式來傳輸
└ 大部分的操作都是透過監聽與發射事件
Socket.io
// Server API: io(httpServer[, oprions])
io(server);
io.on('connection', function(socket){
// a new user connected
socket.emit('message’, {data: 'Hello World!'});
});
// Client API: io([url][, oprions])
// url defaults to window.location
var socket = io('http://localhost:3000’);
socket.on('message', function(data){
console.log(data.msg);
// Hello World!
});
Server Client
49
練習一下
└ (21) 建立一個 Socket.io 的伺服器端與客戶端
└ 使用 npm 安裝 socket.io 和 socket.io-client
└ 當客戶端連線成功時,伺服器端會發送歡迎訊息 (Hello World!)
練習一下
var server = require('http').createServer();
var io = require('socket.io')(server);
io.on('connection', function(socket){
console.log('a new user connected');
socket.emit('message', { msg: 'Hello World!' });
});
server.listen(3000, function(){
console.log('listening on *: 3000');
});
var io = require('socket.io-client');
var socket = io('http://localhost:3000');
socket.on('message', function(data){
console.log(data.msg);
});
Server Client
21
50
即時聊天室
HTTP Request
(via HTTP)
訪問網頁
51
即時聊天室
‘Hello!’
(via Socket.io)
Hello! Hello!
Hello!
即時聊天
Hello!
52
HTML 是一種用於描述網頁結構與內容的標準標示語言
└ 一個標準的 HTML 檔案其實就是一個網頁
└ 以各個元素來組成一個網頁
└ 元素是由標籤以及內容所構成
└ 一個標籤是由一對小於和大於符號 < > 所組成
└ 並在其中放入元素名稱
└ 一個元素一般會有起始標籤與結束標籤
└ 結束標籤會在元素名稱前,多加上一個斜線 /
└ 一個標準的 HTML 網頁包含以下元素
└ 文件類型、html 元素、head 元素、body 元素和 title 元素
網頁基本架構
<!doctype html>
<html>
<head>
<title>Title</title>
</head>
<body>
</body>
</html>
53
實作基礎頁面
<!doctype html>
<html>
<head>
<title>Socket.io chat</title>
</head>
<body>
<h1>Hello World!</h1>
</body>
</html>
└ (1) 建立一個 html 檔,並且在其中用 h1 元素印出 Hello Wrold!
└ h1 元素為標題元素
└ 直接開始 html 檔即可看到網頁
1
54
└ (2) 建立 HTTP 伺服器
└ 收到請求時,回傳 html 網頁
└ 使用 fs 模組讀取網頁
└ node.js 內建的核心模組
└ fs.readFile(path, callback);
└ 檔案讀取完成後,會傳入 callback
的第二個參數 data
└ 將網頁內容以 utf8 格式傳出
伺服器端
var fs = require('fs');
var server = require('http').createServer(handler);
function handler(req, res) {
fs.readFile(__dirname + '/index.html', function(err, data) {
if (err){
res.writeHead(404);
res.end("opps this doesn't exist - 404");
} else {
res.writeHead(200, {"Content-Type": "text/html"});
res.end(data, "utf8");
}
});
}
server.listen(3000, function(){
console.log('listening on *: 3000');
});
2
55
└ (3) 加入 Socket.io server
└ 當 client 對 server 發送聊天訊息時,
將該訊息轉傳給其他所有的 client
└ 當有新的 client 加入時,監聽它的
‘chat message’ 事件
└ 當有 client 發送 ‘chat message’ 事件時,
調用 io.emit 來轉傳給所有 client
Socket.io Server
var fs = require('fs');
var server = require('http').createServer(handler);
var io = require('socket.io')(server);
function handler(req, res) {
[...]
}
io.on('connection', function(socket){
socket.on('chat message', function(msg){
io.emit('chat message', msg);
});
});
server.listen(3000, function(){
console.log('listening on *: 3000');
});
3
56
聊天室網頁
<!doctype html>
<html>
<head>
<title>Socket.io chat</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.1.0/socket.io.js"></script>
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
</head>
<body>
<ul id="messages"></ul>
<form>
<input id="m"/><button>Send</button>
</form>
</body>
</html>
4
└ (4) 修改 html 網頁,加入聊天內容、輸入框和發送按鈕
└ 使用 script 元素引入 socket.io 和 jquery 模組的 CDN
└ 聊天內容用 ul 項目清單元素呈現,並且給它一個 id message
└ 輸入框和發送按鈕是一對的,因此我們使用 form 表單元素,並在其中加入 input 元素和
button 元素,並給 input 元素一個 id m
57
Socket.io Client
<!doctype html>
<html>
<head>
[...]
</head>
<body>
[...]
<script>
var socket = io();
$('form').submit(function(){
socket.emit('chat message', $('#m').val());
$('#m').val('');
return false;
});
socket.on('chat message', function(msg){
$('#messages').append($('<li>').text(msg));
window.scrollTo(0, document.body.scrollHeight);
});
</script>
</body>
</html>
5
└ (5) 完成 Socket.io client
└ 使用 script 標籤來讓我們能在網頁中
插入 JavaScript 程式碼
└ 在程式碼中建立一個 socket.io client
└ 用 $( ) 取得網頁元素
└ # 代表透過 id 取得元素
└ 當發送按鈕被按下時,client 送出
chat message 事件,並將內容一併
傳給 server
└ client 監聽 chat message 事件,當
事件發生時,代表有人發送新的聊天
訊息,因此我們拿這個聊天訊息來在
ul 項目清單元素中加入新的 li 項目元
素
58
測試
$ node index.js

More Related Content

What's hot

Shell,信号量以及java进程的退出
Shell,信号量以及java进程的退出Shell,信号量以及java进程的退出
Shell,信号量以及java进程的退出
wang hongjiang
 
OpenEJB - 另一個選擇
OpenEJB - 另一個選擇OpenEJB - 另一個選擇
OpenEJB - 另一個選擇
Justin Lin
 
Python 于 webgame 的应用
Python 于 webgame 的应用Python 于 webgame 的应用
Python 于 webgame 的应用
勇浩 赖
 
給 GLib 使用者的 libev 簡介
給 GLib 使用者的 libev 簡介給 GLib 使用者的 libev 簡介
給 GLib 使用者的 libev 簡介crabtw
 
Effective linux.1.(commandline)
Effective linux.1.(commandline)Effective linux.1.(commandline)
Effective linux.1.(commandline)
wang hongjiang
 
JAVA内存泄漏及诊断
JAVA内存泄漏及诊断JAVA内存泄漏及诊断
JAVA内存泄漏及诊断
ivannotes
 
程式人雜誌 2015年三月
程式人雜誌 2015年三月程式人雜誌 2015年三月
程式人雜誌 2015年三月
鍾誠 陳鍾誠
 
Javascript之昨是今非
Javascript之昨是今非Javascript之昨是今非
Javascript之昨是今非Tony Deng
 
Jni攻略之八――操作对象的构造方法
Jni攻略之八――操作对象的构造方法Jni攻略之八――操作对象的构造方法
Jni攻略之八――操作对象的构造方法yiditushe
 
Effective java 摘選條目分享 1 - 物件、複合、可變性、leak
Effective java   摘選條目分享 1 - 物件、複合、可變性、leakEffective java   摘選條目分享 1 - 物件、複合、可變性、leak
Effective java 摘選條目分享 1 - 物件、複合、可變性、leak
Kane Shih
 
JavaScript 教程
JavaScript 教程JavaScript 教程
JavaScript 教程
Bobby Zhou
 
改善程序设计技术的50个有效做法
改善程序设计技术的50个有效做法改善程序设计技术的50个有效做法
改善程序设计技术的50个有效做法crasysatan
 
Jscex:案例、经验、阻碍、展望
Jscex:案例、经验、阻碍、展望Jscex:案例、经验、阻碍、展望
Jscex:案例、经验、阻碍、展望jeffz
 
异步编程与浏览器执行模型
异步编程与浏览器执行模型异步编程与浏览器执行模型
异步编程与浏览器执行模型
keelii
 
Effective linux.2.(tools)
Effective linux.2.(tools)Effective linux.2.(tools)
Effective linux.2.(tools)
wang hongjiang
 
Wind.js无障碍调试与排错
Wind.js无障碍调试与排错Wind.js无障碍调试与排错
Wind.js无障碍调试与排错jeffz
 
Groovy Introduction for Java Programmer
Groovy Introduction for Java ProgrammerGroovy Introduction for Java Programmer
Groovy Introduction for Java Programmer
Li Ding
 
Java多线程设计模式
Java多线程设计模式Java多线程设计模式
Java多线程设计模式Tony Deng
 
Javascript share
Javascript shareJavascript share
Javascript share
Xu Mac
 
從 Singleton 談 constructor
從 Singleton 談 constructor從 Singleton 談 constructor
從 Singleton 談 constructor
Luba Tang
 

What's hot (20)

Shell,信号量以及java进程的退出
Shell,信号量以及java进程的退出Shell,信号量以及java进程的退出
Shell,信号量以及java进程的退出
 
OpenEJB - 另一個選擇
OpenEJB - 另一個選擇OpenEJB - 另一個選擇
OpenEJB - 另一個選擇
 
Python 于 webgame 的应用
Python 于 webgame 的应用Python 于 webgame 的应用
Python 于 webgame 的应用
 
給 GLib 使用者的 libev 簡介
給 GLib 使用者的 libev 簡介給 GLib 使用者的 libev 簡介
給 GLib 使用者的 libev 簡介
 
Effective linux.1.(commandline)
Effective linux.1.(commandline)Effective linux.1.(commandline)
Effective linux.1.(commandline)
 
JAVA内存泄漏及诊断
JAVA内存泄漏及诊断JAVA内存泄漏及诊断
JAVA内存泄漏及诊断
 
程式人雜誌 2015年三月
程式人雜誌 2015年三月程式人雜誌 2015年三月
程式人雜誌 2015年三月
 
Javascript之昨是今非
Javascript之昨是今非Javascript之昨是今非
Javascript之昨是今非
 
Jni攻略之八――操作对象的构造方法
Jni攻略之八――操作对象的构造方法Jni攻略之八――操作对象的构造方法
Jni攻略之八――操作对象的构造方法
 
Effective java 摘選條目分享 1 - 物件、複合、可變性、leak
Effective java   摘選條目分享 1 - 物件、複合、可變性、leakEffective java   摘選條目分享 1 - 物件、複合、可變性、leak
Effective java 摘選條目分享 1 - 物件、複合、可變性、leak
 
JavaScript 教程
JavaScript 教程JavaScript 教程
JavaScript 教程
 
改善程序设计技术的50个有效做法
改善程序设计技术的50个有效做法改善程序设计技术的50个有效做法
改善程序设计技术的50个有效做法
 
Jscex:案例、经验、阻碍、展望
Jscex:案例、经验、阻碍、展望Jscex:案例、经验、阻碍、展望
Jscex:案例、经验、阻碍、展望
 
异步编程与浏览器执行模型
异步编程与浏览器执行模型异步编程与浏览器执行模型
异步编程与浏览器执行模型
 
Effective linux.2.(tools)
Effective linux.2.(tools)Effective linux.2.(tools)
Effective linux.2.(tools)
 
Wind.js无障碍调试与排错
Wind.js无障碍调试与排错Wind.js无障碍调试与排错
Wind.js无障碍调试与排错
 
Groovy Introduction for Java Programmer
Groovy Introduction for Java ProgrammerGroovy Introduction for Java Programmer
Groovy Introduction for Java Programmer
 
Java多线程设计模式
Java多线程设计模式Java多线程设计模式
Java多线程设计模式
 
Javascript share
Javascript shareJavascript share
Javascript share
 
從 Singleton 談 constructor
從 Singleton 談 constructor從 Singleton 談 constructor
從 Singleton 談 constructor
 

Similar to 180518 ntut js and node

學好 node.js 不可不知的事
學好 node.js 不可不知的事學好 node.js 不可不知的事
學好 node.js 不可不知的事
Ben Lue
 
程式人雜誌 2015年五月
程式人雜誌 2015年五月程式人雜誌 2015年五月
程式人雜誌 2015年五月
鍾誠 陳鍾誠
 
程式人雜誌 -- 2015 年5月號
程式人雜誌 -- 2015 年5月號程式人雜誌 -- 2015 年5月號
程式人雜誌 -- 2015 年5月號
鍾誠 陳鍾誠
 
潜力无限的编程语言Javascript
潜力无限的编程语言Javascript潜力无限的编程语言Javascript
潜力无限的编程语言Javascriptjay li
 
D2_node在淘宝的应用实践_pdf版
D2_node在淘宝的应用实践_pdf版D2_node在淘宝的应用实践_pdf版
D2_node在淘宝的应用实践_pdf版Jackson Tian
 
Node.js在淘宝的应用实践
Node.js在淘宝的应用实践Node.js在淘宝的应用实践
Node.js在淘宝的应用实践taobao.com
 
107个常用javascript语句 oss 计算技术 - ossez info of tech
107个常用javascript语句   oss 计算技术 - ossez info of tech107个常用javascript语句   oss 计算技术 - ossez info of tech
107个常用javascript语句 oss 计算技术 - ossez info of tech
YUCHENG HU
 
JavaScript Code Quality
JavaScript Code QualityJavaScript Code Quality
JavaScript Code Quality
Joseph Chiang
 
用Jquery实现拖拽层
用Jquery实现拖拽层用Jquery实现拖拽层
用Jquery实现拖拽层yiditushe
 
The Evolution of Async Programming (GZ TechParty C#)
The Evolution of Async Programming (GZ TechParty C#)The Evolution of Async Programming (GZ TechParty C#)
The Evolution of Async Programming (GZ TechParty C#)jeffz
 
千呼萬喚始出來的Java SE 7
千呼萬喚始出來的Java SE 7千呼萬喚始出來的Java SE 7
千呼萬喚始出來的Java SE 7
javatwo2011
 
Browser vs. Node.js Jackson Tian Shanghai
Browser vs. Node.js   Jackson Tian ShanghaiBrowser vs. Node.js   Jackson Tian Shanghai
Browser vs. Node.js Jackson Tian Shanghai
Jackson Tian
 
Ecma script edition5-小试
Ecma script edition5-小试Ecma script edition5-小试
Ecma script edition5-小试lydiafly
 
Javascript autoload
Javascript autoloadJavascript autoload
Javascript autoloadjay li
 
jQuery底层架构
jQuery底层架构jQuery底层架构
jQuery底层架构fangdeng
 
JavaScript Advanced Skill
JavaScript Advanced SkillJavaScript Advanced Skill
JavaScript Advanced Skill
firestoke
 
JCConf2015: groovy to gradle
 JCConf2015: groovy to gradle JCConf2015: groovy to gradle
JCConf2015: groovy to gradle
Ching Yi Chan
 
Node js实践
Node js实践Node js实践
Node js实践myzykj
 
深入剖析Concurrent hashmap中的同步机制(上)
深入剖析Concurrent hashmap中的同步机制(上)深入剖析Concurrent hashmap中的同步机制(上)
深入剖析Concurrent hashmap中的同步机制(上)wang hongjiang
 

Similar to 180518 ntut js and node (20)

學好 node.js 不可不知的事
學好 node.js 不可不知的事學好 node.js 不可不知的事
學好 node.js 不可不知的事
 
程式人雜誌 2015年五月
程式人雜誌 2015年五月程式人雜誌 2015年五月
程式人雜誌 2015年五月
 
程式人雜誌 -- 2015 年5月號
程式人雜誌 -- 2015 年5月號程式人雜誌 -- 2015 年5月號
程式人雜誌 -- 2015 年5月號
 
潜力无限的编程语言Javascript
潜力无限的编程语言Javascript潜力无限的编程语言Javascript
潜力无限的编程语言Javascript
 
D2_node在淘宝的应用实践_pdf版
D2_node在淘宝的应用实践_pdf版D2_node在淘宝的应用实践_pdf版
D2_node在淘宝的应用实践_pdf版
 
Node.js在淘宝的应用实践
Node.js在淘宝的应用实践Node.js在淘宝的应用实践
Node.js在淘宝的应用实践
 
107个常用javascript语句 oss 计算技术 - ossez info of tech
107个常用javascript语句   oss 计算技术 - ossez info of tech107个常用javascript语句   oss 计算技术 - ossez info of tech
107个常用javascript语句 oss 计算技术 - ossez info of tech
 
JavaScript Code Quality
JavaScript Code QualityJavaScript Code Quality
JavaScript Code Quality
 
用Jquery实现拖拽层
用Jquery实现拖拽层用Jquery实现拖拽层
用Jquery实现拖拽层
 
The Evolution of Async Programming (GZ TechParty C#)
The Evolution of Async Programming (GZ TechParty C#)The Evolution of Async Programming (GZ TechParty C#)
The Evolution of Async Programming (GZ TechParty C#)
 
千呼萬喚始出來的Java SE 7
千呼萬喚始出來的Java SE 7千呼萬喚始出來的Java SE 7
千呼萬喚始出來的Java SE 7
 
Browser vs. Node.js Jackson Tian Shanghai
Browser vs. Node.js   Jackson Tian ShanghaiBrowser vs. Node.js   Jackson Tian Shanghai
Browser vs. Node.js Jackson Tian Shanghai
 
Sun java
Sun javaSun java
Sun java
 
Ecma script edition5-小试
Ecma script edition5-小试Ecma script edition5-小试
Ecma script edition5-小试
 
Javascript autoload
Javascript autoloadJavascript autoload
Javascript autoload
 
jQuery底层架构
jQuery底层架构jQuery底层架构
jQuery底层架构
 
JavaScript Advanced Skill
JavaScript Advanced SkillJavaScript Advanced Skill
JavaScript Advanced Skill
 
JCConf2015: groovy to gradle
 JCConf2015: groovy to gradle JCConf2015: groovy to gradle
JCConf2015: groovy to gradle
 
Node js实践
Node js实践Node js实践
Node js实践
 
深入剖析Concurrent hashmap中的同步机制(上)
深入剖析Concurrent hashmap中的同步机制(上)深入剖析Concurrent hashmap中的同步机制(上)
深入剖析Concurrent hashmap中的同步机制(上)
 

180518 ntut js and node

  • 2. 2 └ JavaScript └ 變數 └ 陣列 └ 函式 └ 物件 └ 條件與迴圈 └ Node.js └ 生態系 └ 基礎練習 └ Callback └ 建構式 └ 繼承 └ 模組化 └ 事件發射器 課程綱要 └ 第三方模組 └ npm └ lodash └ 伺服器 └ http server └ socket.io └ 即時聊天室 投影片位置:SlideShare – ntut js and node
  • 6. 6 變數 規則 └ 第一個字元不可是數字 └ 只能是字母、底線和錢字號 └ 不可為關鍵字 └ 如 If、for、this 等等 └ 區分大小寫 └ myname、MYNAME 為不同變數 └ 慣例使用小駝峰命名 └ 如 myName、mySchool └ 無型別 └ 以逗號分隔多個變數 關鍵字 └ var └ let └ 只有在 let 宣告的範疇中有效 └ 沒有變數提升 (hoisting) └ const └ 用來宣告常數 └ 宣告時需指定值 └ 沒有變數提升 (hoisting) // 正確 var myName; var _func; var $i; // 錯誤 var 01x; var @test; var #dash; var a = 10, b = 'test';
  • 7. 7 變數範疇 一個變數的範疇 (scope) 是指程式碼中該變數有定義的區域 └ JavaScript 有兩種變數範疇:全域變數和區域變數 └ 區域變數的優先序比同名稱的全域變數高 └ 使用 var 在函式內宣告的變數為區域變數 └ 使用 let 在函式、for 區塊、if 區塊、或純區塊內宣告的變數為區域變數 var scope = 'global'; function checkScope() { var scope = 'local’; console.log(scope); // local } checkScope(); console.log(scope); // global let x = 1; if (true) { let x = 2; console.log(x); // 2 } console.log(x); // 1 var x = 1; if (true) { var x = 2; console.log(x); // 2 } console.log(x); // 2
  • 8. 8 變數提升 console.log(a); var a = 10; console.log(a); undefined 10 變數宣告會被提升 (hoisting) 到該範疇的最上方 └ 變數初值設定的位置不變 └ let 和 const 沒有變數提升 console.log(a); let a = 10; ReferenceError: a is not defined console.log(a); const a = 10; ReferenceError: a is not defined
  • 9. 9 物件是一堆名稱與值的組合 └ 資料與行為的封裝 └ 擬人化、擬物化 └ 物件擁有紀錄資料與行為的屬性 └ 每個屬性就是一對名稱與值 └ 屬性值可以是任意 JavaScript 的值 └ 若值為函式,我們稱它為物件的方法 (method) └ JavaScript 中所有東西都是物件 └ 不論是數字、字串、陣列、函式等等 物件 var person = {}; person.name = 'Jack'; person['age'] = 26; var person = { name: 'Jack', age: 26, friends: ['Hedy', 'Peter', 'Simen'], parents: { father: 'Eric’, mother: 'Ann' }, speak: function (text) { console.log(text); } }; var person = { name: 'Jack', age: 26 };
  • 10. 10 一個陣列是一組值的有序群集 └ 其中的值稱為元素 (element) └ 元素的位置稱為索引 (index) └ 第一個元素的索引為 0 └ 陣列中不同元素可以是不同型別 └ 只支援一維陣列 └ 但可以在陣列放入陣列來實現二維陣列 └ 每個陣列都有 length (長度) 屬性 陣列 var num = [1, 3, 7, 9, 21, 43]; var name = ['Simen', 'Hedy', 'Peter']; console.log(num.length); // 6 console.log(name.length); // 3 var array = ['Hello', ' World', '!']; console.log(array[0] + array[1] + array[2]); array[1] = ' JavaScript'; console.log(array[0] + array[1] + array[2]); Hello World! Hello JavaScript! var array = [[‘x1’, ‘x2’], [‘y1’, ‘y2’]]; console.log(array[0][1]); // x2
  • 11. 11 函式是一段程式碼,可被多次執行 └ 使用關鍵字 function 來定義 └ 未定義名稱的函式為匿名函式 └ 函式有兩種定義的方式 └ 函式宣告式與函式運算式 └ 函式宣告會被提升 (hoisted) └ 函式也是一個物件 函式 function add (x, y) { return x + y; } var sum = add(2, 3); console.log(sum); var greet = function (name) { console.log('Hello ' + name + '!'); } greet('Simen'); function greet (name) { console.log('Hello ' + name + '!'); } greet('Simen'); (function (name) { console.log('Hello ' + name + '!’); }('Simen'));
  • 13. 13 If 是條件判斷最基本的語法 └ 條件必須是 Boolean 值或運算式 └ 若是其他值,則會被自動轉型為 Boolean 值 └ 用 else if 來判斷多個條件 └ else if 數量沒有限制 └ 用 else 處理條件不符合的情況 └ 判斷式是由上到下循序執行 └ 當一個條件成立時,後面的條件不再繼續判斷 If if (條件) { 條件為 true 時執行此程式 } if (條件1) { 條件1為 true 時執行此程式 } else if (條件2) { 條件1不為 true,但條件2為 true 時執行此程式 } else { 條件皆不為 true 時執行此程式 } function description(height) { if (height < 165) { console.log('矮'); } else if (height >= 165 && height < 175) { console.log('平均'); } else { console.log('高'); } } description(173); // '平均'
  • 14. 14 判斷不同情況下執行不同的程式碼 └ 查對條件與標籤 └ 用 break 跳出 switch └ 可以用 return 取代 └ 用 default 定義沒有相符的標籤時執 行的程式碼 switch switch(條件) { case 標籤: 如果條件 === 標籤時執行此程式 break; default: 若沒有與條件相符的標籤時執行此程式 } function isTodayWeekend() { var day = new Date().getDay(); switch(day) { case 6: console.log('Today is Saturday’); break; case 0: console.log('Today is Sunday'); break; default: console.log('Today is not weekend'); } isTodayWeekend(); // 'Today is not weekend'
  • 15. 15 while 是迴圈最基本的語法 └ 可用來創建無窮迴圈 └ do / while 在迴圈底部才判斷條件 └ 也就是說本體程式碼至少會被執行一次 └ do 迴圈結尾一定要分號 while while (條件) { 條件為 true 時執行程式,並重複迴圈。 } var a = 0; while (a < 5) { console.log(a); a++; // a = a + 1 } do { 執行此程式後判斷條件,若條件為 true 時重複迴圈。 } while (條件); var b = 0; do { console.log(b); b++; } while (b < 5);
  • 16. 16 for 迴圈經常比 while 來得便利 └ 簡化某種共通形式的迴圈 └ 初始化、條件判斷、更新 └ 任一個都可以省略 └ 但兩個分號不可省略 for for (初始化; 條件判斷; 更新) { 條件為 true 時執行程式,並重複迴圈 } var sum; for (var i = 0; i < 5; i ++) { sum = sum + i; } console.log(sum); // 10
  • 18. 18 Node.js 將 JavaScript 推向另一個境界! └ Real-time Web Server └ 單執行緒 └ 事件驅動架構 └ 非同步式 I/O Node.js Node.js Core Node.js Bindings (C++) Google V8 (C++) libuv JavaScript Engine Cross-platform Async I/O
  • 19. 19 └ 套件管理系統與蓬勃發展的生態系 Node.js 生態系 Node.js Native Modules 3rd-party Modules http stream events buffer process … express lodash q async mocha … Our Node.js Application http … express lodash async … npm install <module> npm is not only a node package manager!
  • 20. 20 基礎練習 └ (01) 用 console.log() 印出 Hello World! └ (02) 宣告一個變數 x,並其為字串 “Hello World!”,然後印出 x 條件與迴圈 └ (03) 使用 while 迴圈印出 10 次 Hello World! └ (04) 使用 for 迴圈印出 10 次 Hello World! └ (05) 在 for 迴圈中,當執行第 i 次且 i 是奇數才印出 “Hello World!” (使用 if ) 從 Hello World 開始 3 mins 5 mins
  • 21. 21 你可以偷看一下 console.log('Hello World!'); var x = 'Hello World!'; console.log(x); for (var i = 0; i < 10; i++) { console.log('Hello World!'); } var i = 0; while (i < 10) { console.log('Hello World!'); i++; } for (var i = 0; i < 10; i++) { if ((i%2) !== 0) console.log('Hello World!'); } 01 02 04 03 05
  • 22. 22 函式 └ (06) 將打印 Hello World! 包裝成一支函式 hello(),然後呼叫它 物件 └ (07) 建立一個代表人 (person) 物件,該物件要包含有 name、gender 和 age 屬性, 並且印出 person 物件與其中的屬性 name └ (08) 呈上,在人的物件中,加入方法 speak(),這個方法會傳入一個參數 text,並且 它會印出傳入的參數 來練習函式和物件 2 mins 5 mins
  • 23. 23 你可以偷看一下 function hello() { console.log('Hello World!'); } hello(); 06 var person = { name: 'John', gender: 'man', age: 20 }; console.log(person); console.log(person.name); 07 var person = { name: 'John', gender: 'man', age: 20, speak: function (text) { console.log(text); } }; person.speak('Hi Hi~'); 08
  • 24. 24 Callback └ 回呼函式、回調函式 └ 當呼叫一個函式 a 時,給他另一個函式 b; 當某種條件成立時 ,就回過頭呼叫函式 b 練習一下 └ (09) 寫一支函式 repeatHello(times, callback),然後試著呼叫它來執行 10 次 hello();這裡的 callback 應該放誰呢? 什麼是 Callback function a (x, y, callback) { // ... do something callback(); } function b () { // I am a function } a('hello', 88, b); 4 mins
  • 25. 25 你可以偷看一下 function hello() { console.log('Hello World!'); } function repeatHello(times, callback) { for (var i = 0; i < times; i++) { callback(); } } repeatHello(10, hello); 09
  • 26. 26 建構式 └ 建立類別 └ 根據類別建立新的物件實例 └ 與 new 運算子一起使用 └ 名稱字首大寫 └ 原型:prototype └ JavaScript 中所有物件都具有 prototype └ Object.prototype、Array.prototype、 Function.prototype └ 每 new 一個新的物件實例時,所有屬性都會被 new 一份出來,但原型就不會,因為是「繼承」 的概念! 建構式 Class: Person Name Age Gender Object: Peter Name: Peter Age: 24 Gender: men Object: Simen Name: Simen Age: 36 Gender: men Object: Hedy Name: Hedy Age: 23 Gender: women function Person(name) { this.name = name; } Person.prototype.hello = function () {}; var john = new Person('John');
  • 27. 27 this └ 會指向調用函數的物件實例 └ 在不同的場合使用它所指向的對象會不同 └ 一般函式:根據是否為嚴格模式有所差異,在稀鬆模式中 this 會參考到全域物件;在嚴格模式中 this 為 undefined └ 建構式:this 參考到實例 └ 方法:this 參考到調用該方法的物件 this var savedThis; function Constr() { savedThis = this; } var inst = new Constr(); console.log(savedThis === inst); // true var obj = { method: function () { console.log(this === obj); // true } } obj.method(); 'use strict'; console.log(this); // undefined 1 2 3 1 2 3
  • 28. 28 建構式 └ (10) 建立一個 Person 建構式 └ 屬性:name, age, gender └ 方法:hello └ hello 方法會印出 “Hello, I am xxx.” └ xxx 為新增實例時傳入的名字 └ 新增一個 Person 的實例 練習一下 5 mins function Person(name, gender, age) { this.name = name; this.gender = gender; this.age = age; } Person.prototype.hello = function () { console.log("Hello, I am " + this.name + "."); }; var john = new Person('John', 'man', 20); console.log(john); john.hello(); 10
  • 29. 29 建構式 └ (11) 建立一個 Student 的建構式 └ 屬性:name, age, gender, school └ 方法:hello, greet └ greet 方法會印出 “Hello, I am xxx.” 和 “A student from ooo” └ xxx 為新增實例時傳入的名字 └ ooo 為新增實例時傳入的學校 └ 新增一個 Student 的實例 練習一下 function Student(name, gender, age, school) { this.name = name; this.gender = gender; this.age = age; this.school = school; } Student.prototype.hello = function () { console.log("Hello, I am " + this.name + "."); }; Student.prototype.greet = function () { console.log("Hello, I am " + this.name + “."); console.log("A student from " + this.school + “."); }; var john = new Student('John', 'man', 20, 'NTU'); console.log(john); john.hello(); john.greet(); 115 mins
  • 30. 30 繼承另一個物件的屬性與方法 └ 實現物件原型繼承的函式 util.inherits() └ util.inherits(A, B) 是把 B.prototype 複製到 A 身上 └ 使用 call() 繼承屬性 └ 讓父建構式用子建構式的 this 來執行初始化 └ call() 是 Function.prototype 中的方法 練習一下 └ (12) 使用 util.inherits() 讓 Student 繼承自 Person └ 屬性:school └ 方法:greet 重寫好麻煩:繼承 8 mins function Student(name, school) { Person.call(this, name); this.school = school; } util.inherits(Student, Person); var john = new Student('John', 'NTUT'); function Person(name) { this.name = name; } Person.prototype.hello = function () {};
  • 31. 31 你可以偷看一下 var util = require('util'); // Class: Person function Person(name, gender, age) { this.name = name; this.gender = gender; this.age = age; } Person.prototype.hello = function () { console.log("Hello, I am " + this.name + "."); }; // Class: Student function Student(name, gender, age, school) { Person.call(this, name, gender, age); this.school = school; } util.inherits(Student, Person); Student.prototype.greet = function () { console.log("Hello, I am " + this.name + “."); console.log("A student from " + this.school); }; var john = new Student('John', 'man', 20, 'NTUT'); john.hello(); john.greet(); 12   這個程式寫完後,請試著單獨拿掉 ,執行看看結果如何。然後, 試著單獨拿掉  再看看結果如何。如果有異狀,想想看為什麼? 引用 Node.js 原生模組 util
  • 32. 32 模組是 Node.js 的重要支柱 └ 將程式拆分、封裝 └ 第三方模組 └ require() 載入模組 └ module.exports 公開模組介面 └ module.exports 初始值是一個物件 └ exports 也可以公開模組介面,但要注意他是 module.exports 初始值的參考 練習一下 └ (13) 讓 Person 成為一個模組,讓 Student 引用 模組系統 5 mins var name = 'peter' function hello() { console.log("Hello, I am " + name + "."); } module.exports = hello; var hello = require(‘./hello’); hello(); var name = 'peter' exports.hello = function () { console.log("Hello, I am " + name + "."); } var obj = require(‘./hello’); obj.hello();
  • 33. 33 你可以偷看一下 // Class: Person function Person(name, gender, age) { this.name = name; this.gender = gender; this.age = age; } Person.prototype.hello = function () { console.log("Hello, I am " + this.name + "."); }; module.exports = Person; var util = require('util'); var Person = require('./13_Person'); // Class: Student function Student(name, gender, age, school) { // 略 } util.inherits(Student, Person); Student.prototype.greet = function () { // 略 }; var john = new Student('John', 'man', 20, 'NTU’); console.log(john); john.hello(); john.greet(); 13 匯出 Person 建構子 匯入 Person 建構子
  • 34. 34 event 是 Node.js 最重要的模組 └ Node.js 是事件驅動式,而 events 物件提供唯一的介面 └ events 只提供了一個建構式:EventEmitter └ 大多時候我們會讓物件繼承它,而不是直接使用 └ EventEmitter 提供事件發射與事件監聽器功能 └ .emit() 發射事件 └ .on() 新增事件監聽器 練習一下 └ (14) 新增一個 NewEmitter 建構式,並讓該建構式繼承事件發射器 └ 新增一個 newEmitter 實例 └ 試著每 3 秒引發事件 'show_me',然後在監聽器中印出 Hello World! 事件發射器 5 mins emitter.on('greet', function(name) { console.log('Hello ' + name + "."); }); emitter.emit('greet’, 'peter’);
  • 35. 35 你可以偷看一下 var util = require('util'); var EventEmitter = require('events').EventEmitter; function NewEmitter() {} util.inherits(NewEmitter, EventEmitter); var newEmitter = new NewEmitter(); newEmitter.on('show_me', function() { console.log('Hello World!'); }); setInterval(function () { newEmitter.emit('show_me'); }, 3000); 16
  • 37. 37 Git 是一套分散式版本管理系統 └ 支援本地操作、備份容易 └ 功能強大且具彈性的分支與合併 Github 是軟體原始碼代管服務 └ 世界上最大的程式碼存放網站和開源社群 └ 個人和組織建立和存取保管中的程式碼 └ 共同軟體開發功能 └ 完整的 Git 版控支援 開源無所不在 GitHub
  • 38. 38 Node.js 強大靈活的套件管理員 └ 目前已有上萬個協力廠商模組 └ 一行指令就能安裝別人寫好的模組 └ 安裝指令:npm install <package name> └ 模組被安裝到 node_modules 目錄 └ 安裝前 npm 會先檢查目錄中是否已存在指定模組 └ 安裝 Node.js 會連帶安裝 npm Node Package Manager npm
  • 39. 39 └ npm init └ 初始化專案資訊 └ 產生 package.json └ npm install <package name> └ 安裝指定套件到 node_module 目錄 └ npm 會先檢查當下的 node_module 目錄 └ npm install <package name> -save └ 安裝指定套件到 node_module 目錄 └ 並將該模組與其版本寫入 package.json └ npm install <package name> -g └ 安裝指定套件到全域目錄 npm 常用指令 └ npm install └ 根據 package.json 安裝專案所需的相依套件 └ npm update <package name> └ 更新專案中的指定模組 └ npm update └ 更新專案中的所有模組
  • 40. 40 package.json 定義模組的相依套件及資訊 └ npm install 指令根據它自動下載相依模組 └ 欄位簡述 └ name:模組名稱 └ version:模組版本號 └ decription:模組的簡短描述 └ main:程式進入點 └ script:腳本指令 └ dependencies:模組所依賴的第三方模組清單 └ devDependencies:模組在開發階段所依賴的第三方模組清單 └ keywords:模組關鍵字 └ author:模組作者 └ license:模組版權 package.json { "name": "npm-example", "version": "0.0.1", "decription": "Experiment", "main": "index.js", "dependencies": { "request": "0.1.0" }, "devDependencies": { "mocha": "2.1.0" }, "script": { "start": "node index.js" }, "keywords": [ "example" ], "author": "PeterEB", "license": "MIT" }
  • 41. 41 一個 JavaScript 實用的工具模組 └ 提供像 Function、Array、Object 原生物件的方法 └ 讓程式碼更佳的簡潔及好維護 └ 效能比原生物件的方法好 └ Underscore 的強化版 lodash 文檔 var _ = require('lodash'); _.defaults({ 'a': 1 }, { 'a': 3, 'b': 2 }); // { 'a': 1, 'b': 2 } _.partition([1, 2, 3, 4], n => n % 2); // [[1, 3], [2, 4]] _.toLower('PETER'); // peter
  • 42. 42 練習一下 └ (17) 新增一個專案,並安裝 lodash └ (18) 建立一個陣列中放入數字 1 – 10,接著找出數字 5 的索引 (index) └ _.indexOf(array, value, [fromIndex = 0]) └ (19) 建立一個 person 物件,接著將各個屬性名稱與屬性值分別印出 └ 包含 name、gender、age 屬性 └ 分別印出 “name: xxx”、“gender: xxx”、“age: xxx” └ _.forEach(collection, iteratee) └ iteratee: function (value, key) 練習一下
  • 43. 43 你可以偷看一下 $ npm init 17 example$ npm install lodash var _ = require('lodash'); var num = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; console.log(_.indexOf(num, 5)); 18 var _ = require('lodash'); var person = { name: 'John', gender: 'man', age: 26 }; _.forEach(person, function(value, key) { console.log(key + ': ' + value); }); 19
  • 45. 45 Node.js 原生的 HTTP 模組 └ 建立 HTTP 伺服器 └ 接收請求、回應請求 └ res.writeHead()、res.write()、res.end() └ 發送請求 http var http = require("http"); http.createServer(function(req, res) { res.writeHead(200, {"Content-Type": "text/html"}); res.write("<h1>Node.js</h1>"); res.end("<p>Hello World! I'm built by Node.js</p>"); }).listen(3000); console.log("HTTP Server is listening at port 3000."); 文檔
  • 46. 46 練習一下 └ (20) 建立一個 HTTP 伺服器,監聽連接埠 80 └ 瀏覽器訪問時會回傳 Hello World! └ http.createServer(handler(req, res)) └ res.end() 練習一下 var http = require("http"); http.createServer(function(req, res) { res.end(“Hello World!"); }).listen(80); console.log("HTTP Server is listening at port 80."); 20
  • 47. 47 讓客戶端與伺服器進行互動通訊的技術 └ 在單個 TCP 連線上進行全雙工通訊 └ HTML5 定義了 WebSocket 協定 └ 使客戶端與伺服器間資料交換變得更加簡單 └ 客戶端與伺服器只須完成一次交握,便能建立持續性連線 └ 交握採用 HTTP 協定,並且只需再交握時攜帶狀態資訊,之後的通訊可省略部分狀態資訊 └ 伺服器能主動向用戶推播資料 └ 不需要對資料更改進行輪詢 └ 使客戶端反應更即時 └ 可用來建立 Real-time Web WebSockets
  • 48. 48 Socket.io 是 WebSockets 更高一層的抽象層模組 └ 提供易用的伺服器端與客戶端模組 └ socket.io 與 socket.io-client └ 支援 Flash、XHR、JSONP 等 └ 在某些瀏覽器不支援 WebSocket 的狀況下,則會自動改用其他的方式來傳輸 └ 大部分的操作都是透過監聽與發射事件 Socket.io // Server API: io(httpServer[, oprions]) io(server); io.on('connection', function(socket){ // a new user connected socket.emit('message’, {data: 'Hello World!'}); }); // Client API: io([url][, oprions]) // url defaults to window.location var socket = io('http://localhost:3000’); socket.on('message', function(data){ console.log(data.msg); // Hello World! }); Server Client
  • 49. 49 練習一下 └ (21) 建立一個 Socket.io 的伺服器端與客戶端 └ 使用 npm 安裝 socket.io 和 socket.io-client └ 當客戶端連線成功時,伺服器端會發送歡迎訊息 (Hello World!) 練習一下 var server = require('http').createServer(); var io = require('socket.io')(server); io.on('connection', function(socket){ console.log('a new user connected'); socket.emit('message', { msg: 'Hello World!' }); }); server.listen(3000, function(){ console.log('listening on *: 3000'); }); var io = require('socket.io-client'); var socket = io('http://localhost:3000'); socket.on('message', function(data){ console.log(data.msg); }); Server Client 21
  • 52. 52 HTML 是一種用於描述網頁結構與內容的標準標示語言 └ 一個標準的 HTML 檔案其實就是一個網頁 └ 以各個元素來組成一個網頁 └ 元素是由標籤以及內容所構成 └ 一個標籤是由一對小於和大於符號 < > 所組成 └ 並在其中放入元素名稱 └ 一個元素一般會有起始標籤與結束標籤 └ 結束標籤會在元素名稱前,多加上一個斜線 / └ 一個標準的 HTML 網頁包含以下元素 └ 文件類型、html 元素、head 元素、body 元素和 title 元素 網頁基本架構 <!doctype html> <html> <head> <title>Title</title> </head> <body> </body> </html>
  • 53. 53 實作基礎頁面 <!doctype html> <html> <head> <title>Socket.io chat</title> </head> <body> <h1>Hello World!</h1> </body> </html> └ (1) 建立一個 html 檔,並且在其中用 h1 元素印出 Hello Wrold! └ h1 元素為標題元素 └ 直接開始 html 檔即可看到網頁 1
  • 54. 54 └ (2) 建立 HTTP 伺服器 └ 收到請求時,回傳 html 網頁 └ 使用 fs 模組讀取網頁 └ node.js 內建的核心模組 └ fs.readFile(path, callback); └ 檔案讀取完成後,會傳入 callback 的第二個參數 data └ 將網頁內容以 utf8 格式傳出 伺服器端 var fs = require('fs'); var server = require('http').createServer(handler); function handler(req, res) { fs.readFile(__dirname + '/index.html', function(err, data) { if (err){ res.writeHead(404); res.end("opps this doesn't exist - 404"); } else { res.writeHead(200, {"Content-Type": "text/html"}); res.end(data, "utf8"); } }); } server.listen(3000, function(){ console.log('listening on *: 3000'); }); 2
  • 55. 55 └ (3) 加入 Socket.io server └ 當 client 對 server 發送聊天訊息時, 將該訊息轉傳給其他所有的 client └ 當有新的 client 加入時,監聽它的 ‘chat message’ 事件 └ 當有 client 發送 ‘chat message’ 事件時, 調用 io.emit 來轉傳給所有 client Socket.io Server var fs = require('fs'); var server = require('http').createServer(handler); var io = require('socket.io')(server); function handler(req, res) { [...] } io.on('connection', function(socket){ socket.on('chat message', function(msg){ io.emit('chat message', msg); }); }); server.listen(3000, function(){ console.log('listening on *: 3000'); }); 3
  • 56. 56 聊天室網頁 <!doctype html> <html> <head> <title>Socket.io chat</title> <script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.1.0/socket.io.js"></script> <script src="https://code.jquery.com/jquery-1.12.4.js"></script> </head> <body> <ul id="messages"></ul> <form> <input id="m"/><button>Send</button> </form> </body> </html> 4 └ (4) 修改 html 網頁,加入聊天內容、輸入框和發送按鈕 └ 使用 script 元素引入 socket.io 和 jquery 模組的 CDN └ 聊天內容用 ul 項目清單元素呈現,並且給它一個 id message └ 輸入框和發送按鈕是一對的,因此我們使用 form 表單元素,並在其中加入 input 元素和 button 元素,並給 input 元素一個 id m
  • 57. 57 Socket.io Client <!doctype html> <html> <head> [...] </head> <body> [...] <script> var socket = io(); $('form').submit(function(){ socket.emit('chat message', $('#m').val()); $('#m').val(''); return false; }); socket.on('chat message', function(msg){ $('#messages').append($('<li>').text(msg)); window.scrollTo(0, document.body.scrollHeight); }); </script> </body> </html> 5 └ (5) 完成 Socket.io client └ 使用 script 標籤來讓我們能在網頁中 插入 JavaScript 程式碼 └ 在程式碼中建立一個 socket.io client └ 用 $( ) 取得網頁元素 └ # 代表透過 id 取得元素 └ 當發送按鈕被按下時,client 送出 chat message 事件,並將內容一併 傳給 server └ client 監聽 chat message 事件,當 事件發生時,代表有人發送新的聊天 訊息,因此我們拿這個聊天訊息來在 ul 項目清單元素中加入新的 li 項目元 素

Editor's Notes

  1. 我們先來看看今天要講那些東西 我們會先從基本的 JavaScript 語法開始講起 ... 再來會介紹 Node.js ... 這邊會做一些基礎的練習,把上面 JS 的語法練習過一遍
  2. 開始之前先來檢查電腦裡有沒有安裝 node js 如果使用 windows 就用指令 cmd 打開命令提示字元 用指令 node -v 如果 VM 裡有裝 ubuntu 就打開 Terminal 用指令 node –v 如果 VM 裡有裝 ubuntu 我比較建議大家用 ubuntu 為什麼呢? 業界的習慣吧 大部分的伺服器都是跑 linux 系統,而且很多模組也只支援 linux 如果電腦裡沒有 node 就到他官網安裝 windows 直接下載 ubuntu 的話到網頁中的 Installing Node.js via package manager 然後執行這兩行指令
  3. 他是無型別的 這隊友在寫 C 或是 Java 的人會非常不習慣 這個特色帶來很多方便 但也造成許多人的困擾 像是 C 語言中若是給的型別不對時 會自動拋錯 JS 則是需要自己去判斷型別 他不需要編譯器,像是 C 語言就需要像是 gcc 這類的編譯器 他和 Java 其實沒什麼太大關係 只是 JavaScript 有些東西是借鑒 Java 如物件導向 但實質上他們是兩個完全不同的語言 現在我們就開始講 JS 的一些基礎語法 過往大家都覺得 JS 是個很簡單的語言 基本上就是只用在前端網頁上 但這幾年因為 Node.js 的出現,讓 JS 在伺服器端、手機端、雲端甚至是 VR 上都大放光彩
  4. 首先要講的是變數 在 JS 中宣告變數是有他的規則的 大駝峰是每個單字自首都大寫 剛剛前面有講到的無型別,你把數字指定給他 他就是數字 你把陣列指定給他 他就是陣列 一個 var 可以宣告多個變數,變數之間以逗號區隔 在宣告變數時,可以直接給定初值 最常用的就是 var 那在 ES6 中又加入了兩個宣告的關鍵字 let 和 const let 和 var 很像 下一頁會詳細介紹兩者的不同 const 只要宣告後就不能再去改他 如果嘗試去修改他系統會拋出錯誤
  5. 什麼是區域變數 在這個大誇號中就是區域變數 scope 的範疇 在這個區域中,區域變數的優先序比同名稱的全域變數高 也就是當我全域變數和區域變數同時有 scope 這個變數,在這區域中我只會取得區域變數 而在這個區域外 我就只會取得全域變數 var 只有在函式中才是區域變數 let 可以在 for 區塊、if 區塊、或者是不帶任何控制目的純區塊中,使用 let 宣告區域變數
  6. 變數提稱是 JS 中一個蠻重要的特性 在全域中就是被提升到程式碼的最上方 在函式中就是被提升到函式的最上方
  7. JavaScript 的基礎型別是物件,而且 JS 中所以東西都是物件 拿一支筆舉例,我們要將這支筆抽象封裝成一個物件,他的資料會有顏色灰色 材質金屬 墨水黑色 行為會有按下去筆會出來 屬性的名稱可以是任意字串 值也可以是 JS 中的任意值,不論是字串數字陣列函式或是物件 要存取物件的屬性有兩種方法 在物件後面加 . 然後加上屬性名稱 在物件後用中誇號 並填入屬性名稱 是邊要注意 第一種方式是直接接上屬性名稱就好 第二種方式要把屬性名稱用字串的方式傳入
  8. 類似列表的物件 元素可以是任何型別,可以是字串、物件、函式甚至是陣列 在 JS 中並沒有二維陣列或是三維陣列,但若想要實現二維陣列,就是讓陣列的元素為陣列 因為陣列是一個物件,所以他會有屬性 其中最常用的就是 length 屬性
  9. 函式本身是一段 JS 的程式碼 我們可以將指定的參數丟到函數中執行 通常用來完成某種特殊功能 或是用來處理資料 當我們調用函式時,程式將會執行我們在函式中定義好的行為 函式就是在把這些重複的事情封裝起來 讓我們可以很簡單的重複使用 每次要打招呼時都要 console.log(...); 現在用一個函式包起來 並且提供一個參數 name 現在打招呼就只要調用 greet(‘xxx’) 然後填入名稱就可以了 函式宣告式 就是直接用 function 然後接函式的名稱 這就是函式宣告式 函式運算式 就是我先用建立一個匿名函式,然後將這個匿名函式指定給一個變數 這兩個最大的差異式,在變數提升時,函式宣告式的整個函式都會被提升上去,而函式運算式只有變數會被提升 還有一種函式是立即函式,當某些事情只需要執行一遍時,我們就會用到立即函式 當然立即函式的功用其實蠻多的,像是可以在裡面做初始化,並且可以避免汙染全域變數
  10. If 是 JavaScript 用來作條件判斷最基本的語法 我們可以想像一下 條件判斷其實就是我們遇到多條分岔路,然後要透過條件來選擇要走哪一條路 先看右邊第一個範例 當條件為 true 時會執行大誇號中的程式 常常 if 我們還會搭配 else if 和 else 來使用 第一個條件判斷用 if 後面的條件判斷用 else if 皆不符合的情況用 else
  11. switch 擅長處理多路分支 在 case 後加上標籤 然後再加上一個冒號 switch 的每個 case 都表示,如果 條件 === 標籤時,就執行這段程式碼 break 會讓程式跳出 switch,如果沒有的話,程式就會繼續進到下一個 case switch 也可以用大於小於來判斷 條件放 true 判斷式放在 case 標籤 如果沒有找到相同的值,就會改找 default 標籤 如果沒有 default 就直接跳過整塊程式碼 也可以只用 return 來結束 switch
  12. 迴圈就是讓程式自己重複執行某段程式碼 while 執行完程式後,會再回到迴圈頂端,重新判斷一次條件 do while 會先執行一次程式,才進行判斷,判斷若成立,則回到迴圈頂端
  13. 大多數的迴圈都有某種計數器,並在迴圈開始時初始化,並在每次迭代前被測試,最後在迴圈主體尾端更新 for 迴圈的主要結構 初始化 條件判斷 更新
  14. JavaScript 早期主要用來開發客戶端 Web 應用程式,但自從 Node.js 的出現,JavaScript 就跨足到伺服器端的應用開發。 就像執行Python、Perl、PHP與Ruby程式一樣,這些語言的能做的事,Node.js幾乎都能做,而且可以做得更好。 它偋棄傳統平台依靠多執行緒來實現高平行的設計想法,而採用了單執行緒、非同步式I/O、事件驅動式的程式設計模型,這帶來極大的效能提升 google V8 引擎是 node.js 的心臟 libuv 主要提供了一個事件迴圈 (event-loop) 還有非同步 I/O (fs, tcp) 可以把這兩個都看成是一個函式庫 除了 v8 和 libuv 外,node.js 本身也做了不少事,如提供 JS 模組與 C++ 模組在內的核心模組給使用者 Node.js還可以呼叫C/C++的程式,這樣可以充分利用已有的諸多函式庫,也可以將對效能要求非常高的部分用C/C++來實現。
  15. Node.js 還有數不進的第三方模組,例如資料庫、Web、硬體控制等等 只要是你需要的工具或應用幾乎都能找的到現成的方案,而這些第三方模組透過 npm 就能輕鬆的套用在我們的應用中。 Node.js堪稱是十多年來各種Web開發經驗集大成者。 Node.js可以是伺服器對使用者提供服務,與 Python、PHP、Ruby on Rials相比,它跳過了Apache、Nginx (engine x) 等HTTP伺服器的架設,直接以前端開發。 Node.js內建了HTTP伺服器支援,你不需要額外架設HTTP伺服器。
  16. 那現在我們用 Hello World 來練習我們前面所學到的基本語法 建立檔案,檔名隨便你們,記得副檔名要是 .js windows 打開資料夾 點檢視 然後就可以修改附檔名 或是在 cmd 中用指令 copy null > test.js console 是一個全域物件,用於提供主控台標準輸出 它是一支很簡單卻是非常常用的函式 在函式中我們可以傳入任意 JS 值 他都會把它印到我們執行的命令列或終端機上 類似C語言的printf( )
  17. 不會沒關係,用抄的,但不要用複製的 抄可以訓練肌肉記憶 海闊天空 掉進水裡你不會淹死,待在水裡你才會淹死,你只有游,不停的向前游。 失敗並不可怕,害怕失敗才真正可怕。
  18. 在 JavaScript 中,函式能被傳入另一個函式中使用 當工作執行完成,或是某種條件成立時,在回條調用一開始傳入的函式 callback 本身是同步 因為他只是調用一個函式 只是我們常常會把 callback 放到非同步的函式中來用,所以有些人會誤以為,我只要有用到 callback 那程式就是非同步的
  19. Javascript 其實並不具有 classes 的觀念 建構式讓我可以做很多像「class」的事 一個函式作為建構式使用時,基本上無需撰寫return,如果建構式有傳回值,那傳回值就會被當作最後名稱所參考的值 物件繼承了物件原型 (Object.prototype) 陣列繼承了陣列原型 (Array.prototype) 函式繼承了函式原型 (Function.prototype) 而這些原型都提供了一些常用的方法
  20. 看了前面兩個範例會發現 Person 和 Student 很像 Student 只比他多了一個方法一個屬性,這樣子重寫好麻煩 util 是 Node.js 內建的核心模組之一 使用時須要引入模組
  21. 我們現在就來看要怎麼使用模組,以及如何實作一個 node.js 的模組。 使用模組的方法很簡單,只要在模組資料夾底下的任何 node.js 程式中,呼叫 require 關鍵字來引入模組,require 會將該模組載入記憶體 使用關鍵字 exports 來將這三個功能匯出,exports 是 module.exports 的參考,而 module.exports 預設是一個空物件,所以我們透過它的參考 exports,來將方法加到該物件中,並匯出給使用者。 模組只會被載入一次 如果有多個檔案用到同一個模組的話,它只會被載入一次
  22. events模組不僅用於使用者程式與Node.js底層事件迴圈的互動,還幾乎與所有模組相依。 大多時候,我們並不會直接使用EventEmitter,而是「讓物件繼承它」,包含像是fs、net、http等,只要是支援事件反應的核心模組都是EventEmitter的子類別。 這麼做的原因是 其次,JavaScript的物件機制是以物件原型為基礎,支援部分多重繼首先,具有某個功能的物件(訂出事件名稱,事件的監聽和發射應該是一個屬於該物件的方法,這樣事件可以比較單純,因為這可以讓物件自己管理自己的事件與監聽器。 承,所以繼承EventEmitter並不會打亂物件原有的繼承關係。 NewEmitter 不用做什麼是 只是我們要練習實際使用的情況
  23. 全世界已有 30% 以上的開放原始碼專案改採 Git 進行版本控管 Git 博大精深 非常多細節可以研究 要講一隔半個學期都不是問題 非常推薦大家多去使用 GitHub 可以去上面看看別人寫得程式碼 或是參予開源專案的開發 你可以修改別人的專案 幫它新增功能做是解決問題 或是在上面發表專案的 issue 或議題 很多公司面試都會看你在 GitHub 參予過哪些開源專案
  24. 他是讓 node.js 獲得成功的重要原因之一 從 Node.js v0.6 後,npm 會隨著 Node.js 自動安裝,因此我們不需要再另外安裝,就能直接使用 npm 的指令
  25. -save –g 放在模組名稱前也可以
  26. Function、Array、Object 原生物件提供了哪些方法呢? Function 的話就是 call apply bind Array 就像是 forEach map pop push 好的工具可以減少某些開發上的時間
  27. collection 是指物件和陣列都適用
  28. HTTP 協定通訊只能由客戶端發起,如果伺服器有連續的狀態變化,客戶端要獲得就必須要輪詢,但這很浪費資源 較少的控制開銷。在連線建立後,伺服器和用戶端之間交換資料時,用於協定控制的封包頭部相對較小。