( 底層透過 http.createServer 建立 Server )
const http = require('http') // node.js 內建 http 相關的 module
const server = http.createServer(handler) // http.createServer(function)
function handler(req, res){ // node.js 會給兩個參數 req、res
console.log(req.url)
res.write('hello!')
res.end() // 把 res 丟回去(結束)
}
server.listen(5001) // 最常 80 part
node index.js
localhost:5001
/favicon.ico
就是網頁標題旁邊的那個小 logores.writeHead(200, {
'Content-Type': 'text/html' // 瀏覽器就知道你想要解析的格式,但有些瀏覽器很聰明會自己幫我們解析
})
expressjs__static
Node.js 中的 __dirname
、__filename
const absolutePath = path.join(__dirname, '../lib/common.js')
or
app.use('/static', express.static(__dirname + '/public'));
npm init
npm install express
const express = require('express')
const app = express()
const port = 5001
app.get('/', (req, res) => {
res.send('hello')
})
app.listen(port, () => {
console.log(`Example app listening on port ${port}!`)
})
然後 terminal run -> node index.js
-> localhost:5001 就會出現 Hello 了
用 Express 製作簡易的留言版
Introduction · Node.js 從無到有,打造一個漂亮乾淨俐落的 RESTful API (gitbooks.io) 試起來!
瀏覽器 -> Apache Sercer -> PHP
瀏覽器 <- Apache Sercer <- PHP
瀏覽器 -> Express Server
瀏覽器 <- Express Server
之前快速筆記過關於 MVC 的定義
terminal npm install ejs
app.use((req, res, next) => {
next()
})
拿 request body 裡面的資料
body parsing middleware
npm install body-parser
const bodyParser = require('body-parser')
app.use(bodyParse.urlencoded({ extend: false }))
app.use(bodyParser.json())
npm install express-session
session middleware
做登入登出功能
app.use(session({
secret: 'keynoard cat',
resave: false,
saveUninitalized: true
app.use(function (req, res, next){
if(!req.session.views){
req.session.views = {}
}
})
}))
重複物件自己做一個 middleware 變全域,res.locals view 都可以拿到
index.js
app.use((req, res, next) => { // 自己做 middleware,就不用一直寫重複物件
res.locals.isLogin = req.session.isLogin || false
res.locals.errorMessage = req.flash('errorMessage')
next()
})
npm install bcrypt
本來在操作資料庫裡的東西 (SQL query) 把他看成物件(Object),
所以用操縱 Object 的方式來操作資料
Sequelize
方法文件裡寫的蠻清楚,多多熟悉就好!
npm install --save sequelize
npm install --save mysql2
npm install --save sequelize-cli
npx sequelize-cli init
npx 可以用 ./node_modules/.bin/sequelize 指令代替(npx 就是這個位置,但有時
後跑比較慢)
./node_modules/.bin/sequelize model:generate --name User --attributes username:string,password:string,nickname:string
./node_modules/.bin/sequelize model:generate --name Comment --attributes content:text
./node_modules/.bin/sequelize db:migrate
./node_modules/.bin/sequelize db:migrate:undo
Sequelize 裡的資料庫關聯
.hasOne
.hasMany
ex.
User.hasMany(Comment) -> 單向關聯到 Comment
Comment.belongsTo(User) -> 建立雙向關係
Heroku
其他類似平台:Google GAE、新浪云 SAE 不過在這之前都沒聽過,只聽過 Heroku
( 底層透過 http.createServer 建立 Server )
const http = require('http') // node.js 內建 http 相關的 module
const server = http.createServer(handler) // http.createServer(function)
function handler(req, res){ // node.js 會給兩個參數 req、res
console.log(req.url)
res.write('hello!')
res.end() // 把 res 丟回去(結束)
}
server.listen(5001) // 最常 80 part
node index.js
localhost:5001
/favicon.ico
就是網頁標題旁邊的那個小 logores.writeHead(200, {
'Content-Type': 'text/html' // 瀏覽器就知道你想要解析的格式,但有些瀏覽器很聰明會自己幫我們解析
})
expressjs__static
Node.js 中的 __dirname
、__filename
const absolutePath = path.join(__dirname, '../lib/common.js')
or
app.use('/static', express.static(__dirname + '/public'));
npm init
npm install express
const express = require('express')
const app = express()
const port = 5001
app.get('/', (req, res) => {
res.send('hello')
})
app.listen(port, () => {
console.log(`Example app listening on port ${port}!`)
})
然後 terminal run -> node index.js
-> localhost:5001 就會出現 Hello 了
用 Express 製作簡易的留言版
Introduction · Node.js 從無到有,打造一個漂亮乾淨俐落的 RESTful API (gitbooks.io) 試起來!
瀏覽器 -> Apache Sercer -> PHP
瀏覽器 <- Apache Sercer <- PHP
瀏覽器 -> Express Server
瀏覽器 <- Express Server
之前快速筆記過關於 MVC 的定義
terminal npm install ejs
app.use((req, res, next) => {
next()
})
拿 request body 裡面的資料
body parsing middleware
npm install body-parser
const bodyParser = require('body-parser')
app.use(bodyParse.urlencoded({ extend: false }))
app.use(bodyParser.json())
npm install express-session
session middleware
做登入登出功能
app.use(session({
secret: 'keynoard cat',
resave: false,
saveUninitalized: true
app.use(function (req, res, next){
if(!req.session.views){
req.session.views = {}
}
})
}))
重複物件自己做一個 middleware 變全域,res.locals view 都可以拿到
index.js
app.use((req, res, next) => { // 自己做 middleware,就不用一直寫重複物件
res.locals.isLogin = req.session.isLogin || false
res.locals.errorMessage = req.flash('errorMessage')
next()
})
npm install bcrypt
本來在操作資料庫裡的東西 (SQL query) 把他看成物件(Object),
所以用操縱 Object 的方式來操作資料
Sequelize
方法文件裡寫的蠻清楚,多多熟悉就好!
npm install --save sequelize
npm install --save mysql2
npm install --save sequelize-cli
npx sequelize-cli init
npx 可以用 ./node_modules/.bin/sequelize 指令代替(npx 就是這個位置,但有時
後跑比較慢)
./node_modules/.bin/sequelize model:generate --name User --attributes username:string,password:string,nickname:string
./node_modules/.bin/sequelize model:generate --name Comment --attributes content:text
./node_modules/.bin/sequelize db:migrate
./node_modules/.bin/sequelize db:migrate:undo
Sequelize 裡的資料庫關聯
.hasOne
.hasMany
ex.
User.hasMany(Comment) -> 單向關聯到 Comment
Comment.belongsTo(User) -> 建立雙向關係
Heroku
其他類似平台:Google GAE、新浪云 SAE 不過在這之前都沒聽過,只聽過 Heroku
by reference
例外
若是使用 object literal 的方式來建立物件,則會變成 by Value,新增了一個記憶體的位置。
JavaScript 是「傳值」或「傳址」?
談談 JavaScript 中 by reference 和 by value 的重要觀念
typeof
console.log(typeof true)
但有些無法靠 typeof 得知
console.log(typepf null)
-> object
console.log(typepf function)
-> function
想判斷是不是陣列
console.log(Array.isArray([]))
較舊的瀏覽器沒有這個方法的話可以用
console.log(Object.prototype.toString,call(null))
[object Array]
primitive type
object type
順帶一提
=
==
===
(指向同一個記憶體位置時才成立)Not a number
isNaN 可以查是不是,但較舊瀏覽器也是不支援
JS Comparison Table
isNaN()
變數的生存範圍
scope chain
inner scope -> test scope -> global scope
Hoisting 順序
function -> 參數 -> variable
直接給例
console.log(age)
var age = 100
輸出結果:undefined
咦?照理來說,程式碼由上往下執行,不是應該 age is not defined
嗎?很奇怪吧,這就是 JS 中的 Hoisting,變數的宣告會被提升到最上面。
再來,以我目前的理解及實作,Hoisting 最重要的地方在於讓程式碼中 function 可以順利宣告及呼叫。至於變數宣告,倒是可以透過良好 coding 習慣解決的。
Execution context (current) |
---|
Execution context (N+2) |
Execution context (N+1) |
Execution context (N) |
Global Execution context |
function 的資訊都在 Execution context 裡,而每個 Execution context 裡都會有相對應的 variable object(暫稱 VO)。
首先,你可以把 VO 想像成就是一個 JavaScript 的物件就好。
再來,VO 什麼時候會用到?你在存取值的時候會用到,例如說 var a = 10 這一句,之前有講過可以分成左右兩塊:
- var a:去 VO 裡面新增一個屬性叫做 a(如果沒有 a 這個屬性的話)並初始化成 undefined
- a = 10:先在 VO 裡面找到叫做 a 的屬性,找到之後設定為 10
更多關於 VO.... 請左轉至 我知道你懂 hoisting,可是你了解到多深? 深入了解,大概滑鼠往下滑 10 下就到了
每 call function 一次,會建立一個新的 EC,但每次 JS 內部調用一個 EC 都會有兩個階段
所以如果我們把 EC 想像成一個物件的話,大概會像這樣
executionContextObject = {
scopeChain: { /* 變數物件 + 所有父代執行環境物件的變數物件*/},
variableObject: {/* 函式的參數/引數,內部的變數和函式*/ },
this: {}
}
變數活性區
myWallet.add(1)
以前可能是用 function call
setter
getter
ES5 時期,透過 .prototype.getName()
prototype
__proto__
constructor
Object.prototype
Function.prototype
new
constrecture
super
- this 是 JavaScript 的一個關鍵字。
- this 是 function 執行時,自動生成的一個內部物件。
- 隨著 function 執行場合的不同,this 所指向的值,也會有所不同。
- 在大多數的情況下, this 代表的就是呼叫 function 的物件 (Owner Object of the function)。
—— What’s THIS in JavaScript ?
- 嚴格模式底下就都是undefined
- 非嚴格模式,瀏覽器底下是window
- 非嚴格模式,node.js 底下是global
—— 淺談 JavaScript 頭號難題 this:絕對不完整,但保證好懂
' use strict ' ;
.call()
.apply()
function log() {
console.log(this);
}
var a = { a: 1, log: log };
var b = { a: 2, log: log };
log(); // undefined
a.log(); // a
b.log.apply(a) // a
Javascript继承机制的设计思想
Javascript 面向对象编程(一):封装
Javascript面向对象编程(二):构造函数的继承
Javascript面向对象编程(二):构造函数的继承
一開始作者設計的時候其實認為不需要設計繼承機制,但 JS 裡面所有數據類型都是對象(object),所以最後還是引入了物件導向的 new 命令,但在 Java 或 C++ 裡使用 new 命令時都會調用「類(Class)」的構造函數,但可能礙於是要做出簡易的腳本語言不增加初學者負擔,於是簡化了設計,所以在 JS 裡的 new 命令後面跟得不是 Class 而是構造函數(constructor)。
但這樣會有一個缺點,就是無法共享屬性和方法造成滿大的資源浪費,因此作者決定為構造函數(constructor)設一個 prototype 屬性。
为了解决从原型对象生成实例的问题,Javascript提供了一个构造函数(Constructor)模式。
所谓"构造函数",其实就是一个普通函数,但是内部使用了this变量。对构造函数使用new运算符,就能生成实例,并且this变量会绑定在实例对象上。
prototype 這個屬性包含了一個對象,所有想共享的屬性、方法都放在這個對象裡; 其他不需要的就放在剛提到的構造函數裡(constructor)。
by reference
例外
若是使用 object literal 的方式來建立物件,則會變成 by Value,新增了一個記憶體的位置。
JavaScript 是「傳值」或「傳址」?
談談 JavaScript 中 by reference 和 by value 的重要觀念
typeof
console.log(typeof true)
但有些無法靠 typeof 得知
console.log(typepf null)
-> object
console.log(typepf function)
-> function
想判斷是不是陣列
console.log(Array.isArray([]))
較舊的瀏覽器沒有這個方法的話可以用
console.log(Object.prototype.toString,call(null))
[object Array]
primitive type
object type
順帶一提
=
==
===
(指向同一個記憶體位置時才成立)Not a number
isNaN 可以查是不是,但較舊瀏覽器也是不支援
JS Comparison Table
isNaN()
變數的生存範圍
scope chain
inner scope -> test scope -> global scope
Hoisting 順序
function -> 參數 -> variable
直接給例
console.log(age)
var age = 100
輸出結果:undefined
咦?照理來說,程式碼由上往下執行,不是應該 age is not defined
嗎?很奇怪吧,這就是 JS 中的 Hoisting,變數的宣告會被提升到最上面。
再來,以我目前的理解及實作,Hoisting 最重要的地方在於讓程式碼中 function 可以順利宣告及呼叫。至於變數宣告,倒是可以透過良好 coding 習慣解決的。
Execution context (current) |
---|
Execution context (N+2) |
Execution context (N+1) |
Execution context (N) |
Global Execution context |
function 的資訊都在 Execution context 裡,而每個 Execution context 裡都會有相對應的 variable object(暫稱 VO)。
首先,你可以把 VO 想像成就是一個 JavaScript 的物件就好。
再來,VO 什麼時候會用到?你在存取值的時候會用到,例如說 var a = 10 這一句,之前有講過可以分成左右兩塊:
- var a:去 VO 裡面新增一個屬性叫做 a(如果沒有 a 這個屬性的話)並初始化成 undefined
- a = 10:先在 VO 裡面找到叫做 a 的屬性,找到之後設定為 10
更多關於 VO.... 請左轉至 我知道你懂 hoisting,可是你了解到多深? 深入了解,大概滑鼠往下滑 10 下就到了
每 call function 一次,會建立一個新的 EC,但每次 JS 內部調用一個 EC 都會有兩個階段
所以如果我們把 EC 想像成一個物件的話,大概會像這樣
executionContextObject = {
scopeChain: { /* 變數物件 + 所有父代執行環境物件的變數物件*/},
variableObject: {/* 函式的參數/引數,內部的變數和函式*/ },
this: {}
}
變數活性區
myWallet.add(1)
以前可能是用 function call
setter
getter
ES5 時期,透過 .prototype.getName()
prototype
__proto__
constructor
Object.prototype
Function.prototype
new
constrecture
super
- this 是 JavaScript 的一個關鍵字。
- this 是 function 執行時,自動生成的一個內部物件。
- 隨著 function 執行場合的不同,this 所指向的值,也會有所不同。
- 在大多數的情況下, this 代表的就是呼叫 function 的物件 (Owner Object of the function)。
—— What’s THIS in JavaScript ?
- 嚴格模式底下就都是undefined
- 非嚴格模式,瀏覽器底下是window
- 非嚴格模式,node.js 底下是global
—— 淺談 JavaScript 頭號難題 this:絕對不完整,但保證好懂
' use strict ' ;
.call()
.apply()
function log() {
console.log(this);
}
var a = { a: 1, log: log };
var b = { a: 2, log: log };
log(); // undefined
a.log(); // a
b.log.apply(a) // a
Javascript继承机制的设计思想
Javascript 面向对象编程(一):封装
Javascript面向对象编程(二):构造函数的继承
Javascript面向对象编程(二):构造函数的继承
一開始作者設計的時候其實認為不需要設計繼承機制,但 JS 裡面所有數據類型都是對象(object),所以最後還是引入了物件導向的 new 命令,但在 Java 或 C++ 裡使用 new 命令時都會調用「類(Class)」的構造函數,但可能礙於是要做出簡易的腳本語言不增加初學者負擔,於是簡化了設計,所以在 JS 裡的 new 命令後面跟得不是 Class 而是構造函數(constructor)。
但這樣會有一個缺點,就是無法共享屬性和方法造成滿大的資源浪費,因此作者決定為構造函數(constructor)設一個 prototype 屬性。
为了解决从原型对象生成实例的问题,Javascript提供了一个构造函数(Constructor)模式。
所谓"构造函数",其实就是一个普通函数,但是内部使用了this变量。对构造函数使用new运算符,就能生成实例,并且this变量会绑定在实例对象上。
prototype 這個屬性包含了一個對象,所有想共享的屬性、方法都放在這個對象裡; 其他不需要的就放在剛提到的構造函數裡(constructor)。
Docker 是一個建立在本地端的虛擬環境,讓我們可以快速的建立、測試跟部署應用程式。
更細一點說的話
Docker 將軟體封裝到名為容器的標準化單位,其中包含程式庫、系統工具、程式碼和執行時間等執行軟體所需的所有項目。使用 Docker,您可以將應用程式快速地部署到各種環境並加以擴展,而且知道程式碼可以執行。—— AWS
const port = process.env.PORT || 3000
伺服器渲染(Server-Side Rendering)
但當專案龐大時易造成前後端混合的程式碼混亂,於是把前後端分開來實作,但分開後,又發現
- 頁面由伺服器產生,每次更新頁面都需要全畫面重新渲染。
- 伺服器取得資料後,需要計算畫面並整頁送出,運算及流量的負荷都太大。
每次 render 頁面時的使用者體驗不好,直到 Gmail 使用的 SPA 方式解決了這樣的問題。
單頁式應用(Single Page Application)
雖然 SPA 可以讓使用者重載新頁面時不會有全空白之類的畫面,解決了上面提到的那些問題,可是這樣一來前端就要開始負責取得資料、處理畫面、頁面跳轉
的阿哩阿雜的問題了.... 於是.... 沒錯!有人就把 MVC 的概念搬來前端實作了!
空殼 HTML 所以 SEO 極差
SPA 的問題只在第一畫面,那就在伺服器先算好第一畫面,其他畫面再透過 JavaScript 動態處理;也就是第一畫面為 SSR,其他畫面是 CSR(Client-Side Rendering),這樣是不是就完美了呢?
這樣做的代價,就是同一個頁面需要實作兩次顯示邏輯(前端後端各一次);幸好 JavaScript 不是一個純粹前端的語言,後端可以跑在 Node.js 中,開發者得以使用大致相同的程式,實現這樣的需求;這種同一份 JavaScript Code 可以跑在前端與後端的程式設計,叫做 Isomorphic JavaScript,同構的 JS。
在這樣的概念出來後,前端框架的 SSR 框架也就應運而生了,例如 React 的 Next,及 Vue 的 Nuxt,都是原本前端框架的語法再擴充,讓原先就熟悉框架的開發者,只需要越過相對小的進入門檻,就能滿足第一頁 SSR 的需求。
除了透過 SSR 框架幫你把頁面的第一次渲染即時算出來,在一些資料相對簡單,變動不太大的網站,也可以選擇透過例如 Prerender 之類的工具,是先把網頁全部算好,儲存成靜態頁面,這樣也可以解決 SEO 的問題。
藉由 Isomorphic JavaScript 的設計,及 Prerender 等工具,第一畫面才會出現的問題就能被解決,關於 SPA 及 SSR 的優缺點取捨,自然也就再也不是問題。
跟自己對不起,我放棄消化成速記了 XD
為什麼現在的前端都在用「框架」?
談談前端框架
為什麼網站要做成 SPA?SSR 的優點是什麼?
前後端分離與 SPA
图解 SSR 等 6 种前端渲染模式
前端 SSR 技術探究
Docker 是一個建立在本地端的虛擬環境,讓我們可以快速的建立、測試跟部署應用程式。
更細一點說的話
Docker 將軟體封裝到名為容器的標準化單位,其中包含程式庫、系統工具、程式碼和執行時間等執行軟體所需的所有項目。使用 Docker,您可以將應用程式快速地部署到各種環境並加以擴展,而且知道程式碼可以執行。—— AWS
const port = process.env.PORT || 3000
伺服器渲染(Server-Side Rendering)
但當專案龐大時易造成前後端混合的程式碼混亂,於是把前後端分開來實作,但分開後,又發現
- 頁面由伺服器產生,每次更新頁面都需要全畫面重新渲染。
- 伺服器取得資料後,需要計算畫面並整頁送出,運算及流量的負荷都太大。
每次 render 頁面時的使用者體驗不好,直到 Gmail 使用的 SPA 方式解決了這樣的問題。
單頁式應用(Single Page Application)
雖然 SPA 可以讓使用者重載新頁面時不會有全空白之類的畫面,解決了上面提到的那些問題,可是這樣一來前端就要開始負責取得資料、處理畫面、頁面跳轉
的阿哩阿雜的問題了.... 於是.... 沒錯!有人就把 MVC 的概念搬來前端實作了!
空殼 HTML 所以 SEO 極差
SPA 的問題只在第一畫面,那就在伺服器先算好第一畫面,其他畫面再透過 JavaScript 動態處理;也就是第一畫面為 SSR,其他畫面是 CSR(Client-Side Rendering),這樣是不是就完美了呢?
這樣做的代價,就是同一個頁面需要實作兩次顯示邏輯(前端後端各一次);幸好 JavaScript 不是一個純粹前端的語言,後端可以跑在 Node.js 中,開發者得以使用大致相同的程式,實現這樣的需求;這種同一份 JavaScript Code 可以跑在前端與後端的程式設計,叫做 Isomorphic JavaScript,同構的 JS。
在這樣的概念出來後,前端框架的 SSR 框架也就應運而生了,例如 React 的 Next,及 Vue 的 Nuxt,都是原本前端框架的語法再擴充,讓原先就熟悉框架的開發者,只需要越過相對小的進入門檻,就能滿足第一頁 SSR 的需求。
除了透過 SSR 框架幫你把頁面的第一次渲染即時算出來,在一些資料相對簡單,變動不太大的網站,也可以選擇透過例如 Prerender 之類的工具,是先把網頁全部算好,儲存成靜態頁面,這樣也可以解決 SEO 的問題。
藉由 Isomorphic JavaScript 的設計,及 Prerender 等工具,第一畫面才會出現的問題就能被解決,關於 SPA 及 SSR 的優缺點取捨,自然也就再也不是問題。
跟自己對不起,我放棄消化成速記了 XD
為什麼現在的前端都在用「框架」?
談談前端框架
為什麼網站要做成 SPA?SSR 的優點是什麼?
前後端分離與 SPA
图解 SSR 等 6 种前端渲染模式
前端 SSR 技術探究
淺談 Session 與 Cookie:一起來讀 RFC
深入 Session 與 Cookie:Express、PHP 與 Rails 的實作
HTTP Session 攻擊與防護
Session 機制可以只靠網址列實作,可以跟 Cookie 一點關係都沒有
只是因為靠 Cookie 來實作 Session 機制的話很方便,所以實際應用都會綁一起
瀏覽器上 HTTP 是無狀態的,所以當我們發送 Request 時,每一個都是不相關的
那問題就來了,怎麼讓它記住狀態?就是靠 session
所以 session 就是一個可以讓 http 變得有狀態(stateful)的東東
而在瀏覽器中,就會透過網址來實作這個機制(當然還有其他實作 session 的方法)
Ex. 網購時,把一個鏡子加入購物車,session 就可以透過網址來儲存我們
「把一個鏡子加入購物車後的狀態」,可能在原本的網址後面加上 ?item=mirror 之類的來儲存狀態
雖然 session 把狀態儲存在網址了,但我們會記得這串網址,下次來的時候給瀏覽器這串網址讓他知道你上次逛到哪嗎?不會
所以只好靠 Server 裡面的 Cookie 機制(Set-cookie)來實作 session
Server (Set-cookie) -> Browser 儲存
或者應該這樣說,Cookie 本來就是為了實作 Session 而生的。藉由標準化的規範,制定了一個專門用來讓瀏覽器與 Server 交換資料的機制,如果用故事來比喻,就好比政府制定說每個人隨身一定要攜帶手機(cookie),然後手機裡面一定要存小明留下來的狀態(session)。
—— 參見白話 Session 與 Cookie:從經營雜貨店開始
在網路世界中,也有很多種方式可以來實作 Session,前面介紹過第一種是網址列,第二種就是靠 Cookie。而 Cookie 就是存在瀏覽器裡的一些資訊。
淺談 Session 與 Cookie:一起來讀 RFC
深入 Session 與 Cookie:Express、PHP 與 Rails 的實作
HTTP Session 攻擊與防護
Session 機制可以只靠網址列實作,可以跟 Cookie 一點關係都沒有
只是因為靠 Cookie 來實作 Session 機制的話很方便,所以實際應用都會綁一起
瀏覽器上 HTTP 是無狀態的,所以當我們發送 Request 時,每一個都是不相關的
那問題就來了,怎麼讓它記住狀態?就是靠 session
所以 session 就是一個可以讓 http 變得有狀態(stateful)的東東
而在瀏覽器中,就會透過網址來實作這個機制(當然還有其他實作 session 的方法)
Ex. 網購時,把一個鏡子加入購物車,session 就可以透過網址來儲存我們
「把一個鏡子加入購物車後的狀態」,可能在原本的網址後面加上 ?item=mirror 之類的來儲存狀態
雖然 session 把狀態儲存在網址了,但我們會記得這串網址,下次來的時候給瀏覽器這串網址讓他知道你上次逛到哪嗎?不會
所以只好靠 Server 裡面的 Cookie 機制(Set-cookie)來實作 session
Server (Set-cookie) -> Browser 儲存
或者應該這樣說,Cookie 本來就是為了實作 Session 而生的。藉由標準化的規範,制定了一個專門用來讓瀏覽器與 Server 交換資料的機制,如果用故事來比喻,就好比政府制定說每個人隨身一定要攜帶手機(cookie),然後手機裡面一定要存小明留下來的狀態(session)。
—— 參見白話 Session 與 Cookie:從經營雜貨店開始
在網路世界中,也有很多種方式可以來實作 Session,前面介紹過第一種是網址列,第二種就是靠 Cookie。而 Cookie 就是存在瀏覽器裡的一些資訊。
译 现代浏览器内部揭秘(第一部分)
Inside look at modern web browser (part 1) | Web | Google Developers
電腦核心是由 CPU 和 GPU 組成
Process 程序(中國稱進程)
Thread 執行緒(中國稱線程)
IPC(Inter Process Communication)指不同 Process 之間溝通
Browser 裡有各種 Process
(ex. Browser Process、GPU Process、Render Process、Plugin Process)
在 Chrome 裡面每開一個 tab 都是一個 Process (tab 就是瀏覽器上方的分頁)
HTML 裡的 iframe 標籤也是一個 Process
/當我們在 Google search input 放入字串時/
/換頁(tab)時/
Renderer process 負責處理 DOM,DOM 是瀏覽器內部對於網頁的一個表示方法、一個資料結構
Renderer process 內有
译 现代浏览器内部揭秘(第一部分)
Inside look at modern web browser (part 1) | Web | Google Developers
電腦核心是由 CPU 和 GPU 組成
Process 程序(中國稱進程)
Thread 執行緒(中國稱線程)
IPC(Inter Process Communication)指不同 Process 之間溝通
Browser 裡有各種 Process
(ex. Browser Process、GPU Process、Render Process、Plugin Process)
在 Chrome 裡面每開一個 tab 都是一個 Process (tab 就是瀏覽器上方的分頁)
HTML 裡的 iframe 標籤也是一個 Process
/當我們在 Google search input 放入字串時/
/換頁(tab)時/
Renderer process 負責處理 DOM,DOM 是瀏覽器內部對於網頁的一個表示方法、一個資料結構
Renderer process 內有
寫出一個 function stars,接收一個參數 n,並且按照規律印出相對應的圖案。
stars(1) 預期輸出:*
stars(3) 預期輸出:******
stars(7) 預期輸出:****************************
function stars(n){
let msg = ''
for(i=0; i<n; i++){
for(j=0;j<=i;j++){
msg += '*'
}
}
console.log(msg)
}
寫出一個 function makeStars,接收一個參數 n,並且根據規律「回傳」字串
makeStars(1) 正確回傳值:*
makeStars(2) 正確回傳值:*\n**
makeStars(5) 正確回傳值:*\n**\n***\n****\n*****
function makeStars(n){
let msg = ''
for(let i=0;i<n; i++){
for(let j=0; j<=i; j++){
msg += '*'
}
msg += '\n'
}
return msg
}
寫出一個函式 stars2,接收一個參數 n,並依照規律印出圖形。
stars2(1) 預期輸出:*
stars2(3) 預期輸出:
*
**
***
**
*
stars2(5) 預期輸出:
*
**
***
****
*****
****
***
**
*
// 參考
function star(i){
var result = ''
for(let j=1; j<=i; j++){
result += '*'
}
return result
}
function stars(val){
for(let i=1; i <= val ; i++){
console.log(star(i))
}
for(let i = val - 1; i >= 1; i--){
console.log(star(i))
}
}
stars(3)
寫一個函式 table,接收一個數字 n,印出 n1 ~ n9 的結果。
table(1) 預期輸出:
1*1 = 1
1*2 = 2
1*3 = 3
1*4 = 4
1*5 = 5
1*6 = 6
1*7 = 7
1*8 = 8
1*9 = 9
table(7) 預期輸出:
7*1 = 1
7*2 = 14
7*3 = 21
7*4 = 28
7*5 = 35
7*6 = 42
7*7 = 49
7*8 = 56
7*9 = 63
function table(n){
for(let i=0; i<=9; i++){
console.log(`${n}*${i} = ${n*i}`)
}
}
寫出一個 function table9to9,並列出 1*1 ~ 9*9
。
table9to9() 預期輸出:
1*1 = 1
1*2 = 2
1*3 = 3
.....
5*1 = 5
5*2 = 10
5*3 = 15
....
9*7 = 63
9*8 = 72
9*9 = 81
function table9to9(){
for(let j=1; j<=9; j++){
for(let i=1; i<=9; i++){
console.log(`${j}*${i} = ${j*i}`)
}
}
}
table9to9()
費式數列的定義為:第 n 個數等於前兩個數的總和,因此這個數列會長的像這樣:1 1 2 3 5 8 13 21 ....
用比較數學一點的講法,就是:
fib(0) = 0
fib(1) = 1
for n >=2, fib(n) = fib(n-1) + fib(n-2)
現在,請你寫出一個 fib 的函式,回傳位在第 n 個位置的數字
fib(1) 預期回傳值:1
fib(2) 預期回傳值:1
fib(8) 預期回傳值:21
function fib(n){
if(n===0) return 0
if(n===1) return 1
return fib(n-2)+fib(n-1)
}
console.log(fib(8))
寫出一個函式 reverse,接收一個字串,並且回傳反轉過後的字串。(禁止使用內建函式 reverse)
reverse("abcd") 預期回傳值:dcba
reverse("12345aa") 預期回傳值:aa54321
function reverse(str){
let msg = ''
for(let i=str.length-1; i>=0; i--){
msg += str[i]
}
console.log(msg)
}
reverse("abcd")
reverse("12345aa")
寫一個函式 swap,接收一個字串,並且回傳大小寫互換後的字串。
swap("Peter") 預期回傳值:pETER
swap("AbCdE") 預期回傳值:aBcDe
// 參考
function swap(str){
let result = '';
for(let i=0;i<=str.length;i++){
if(str[i] <= 'a' && str[i] <= 'z'){
result += str[i].toLowerCase();
}
if(str[i] >= 'A' && str[i] >= 'Z'){
result += str[i].toUpperCase();
}
}
console.log(result)
}
swap("Peter")
swap("AbCdE")
寫出一個函式 findMin,接收一個陣列並回傳陣列中的最小值。(禁止使用內建函式 sort)
findMin([1, 2, 5, 6, 99, 4, 5]) 預期回傳值:1
findMin([1, 6, 0, 33, 44, 88, -10]) 預期回傳值:-10
// 參考
function findMin(arr){
let minNumber = arr[0];
for(let i = 1; i < arr.length;i++){
if(minNumber > arr[i]){
minNumber = arr[i];
}
}
console.log(minNumber)
}
findMin([1, 2, 5, 6, 99, 4, 5])
findMin([1, 6, 0, 33, 44, 88, -10])
寫一個 function findNthMin,接收一個陣列以及一個數字 n,找出第 n 小的數字。(禁止使用內建函式 sort)
提示:假設我要找出第 2 小的值,我只要先找出最小的值然後再把它刪掉,再重新找一次最小的值,就會是第 2 小的值了。
findNthMin([1, 2, 3, 4, 5], 1) 預期回傳值:1
findNthMin([1, 3, 5, 7, 9], 3) 預期回傳值:5
findNthMin([1, 1, 1, 1, 1], 2) 預期回傳值:1
function findNthMin(arr, n){
}
]]>寫出一個 function stars,接收一個參數 n,並且按照規律印出相對應的圖案。
stars(1) 預期輸出:*
stars(3) 預期輸出:******
stars(7) 預期輸出:****************************
function stars(n){
let msg = ''
for(i=0; i<n; i++){
for(j=0;j<=i;j++){
msg += '*'
}
}
console.log(msg)
}
寫出一個 function makeStars,接收一個參數 n,並且根據規律「回傳」字串
makeStars(1) 正確回傳值:*
makeStars(2) 正確回傳值:*\n**
makeStars(5) 正確回傳值:*\n**\n***\n****\n*****
function makeStars(n){
let msg = ''
for(let i=0;i<n; i++){
for(let j=0; j<=i; j++){
msg += '*'
}
msg += '\n'
}
return msg
}
寫出一個函式 stars2,接收一個參數 n,並依照規律印出圖形。
stars2(1) 預期輸出:*
stars2(3) 預期輸出:
*
**
***
**
*
stars2(5) 預期輸出:
*
**
***
****
*****
****
***
**
*
// 參考
function star(i){
var result = ''
for(let j=1; j<=i; j++){
result += '*'
}
return result
}
function stars(val){
for(let i=1; i <= val ; i++){
console.log(star(i))
}
for(let i = val - 1; i >= 1; i--){
console.log(star(i))
}
}
stars(3)
寫一個函式 table,接收一個數字 n,印出 n1 ~ n9 的結果。
table(1) 預期輸出:
1*1 = 1
1*2 = 2
1*3 = 3
1*4 = 4
1*5 = 5
1*6 = 6
1*7 = 7
1*8 = 8
1*9 = 9
table(7) 預期輸出:
7*1 = 1
7*2 = 14
7*3 = 21
7*4 = 28
7*5 = 35
7*6 = 42
7*7 = 49
7*8 = 56
7*9 = 63
function table(n){
for(let i=0; i<=9; i++){
console.log(`${n}*${i} = ${n*i}`)
}
}
寫出一個 function table9to9,並列出 1*1 ~ 9*9
。
table9to9() 預期輸出:
1*1 = 1
1*2 = 2
1*3 = 3
.....
5*1 = 5
5*2 = 10
5*3 = 15
....
9*7 = 63
9*8 = 72
9*9 = 81
function table9to9(){
for(let j=1; j<=9; j++){
for(let i=1; i<=9; i++){
console.log(`${j}*${i} = ${j*i}`)
}
}
}
table9to9()
費式數列的定義為:第 n 個數等於前兩個數的總和,因此這個數列會長的像這樣:1 1 2 3 5 8 13 21 ....
用比較數學一點的講法,就是:
fib(0) = 0
fib(1) = 1
for n >=2, fib(n) = fib(n-1) + fib(n-2)
現在,請你寫出一個 fib 的函式,回傳位在第 n 個位置的數字
fib(1) 預期回傳值:1
fib(2) 預期回傳值:1
fib(8) 預期回傳值:21
function fib(n){
if(n===0) return 0
if(n===1) return 1
return fib(n-2)+fib(n-1)
}
console.log(fib(8))
寫出一個函式 reverse,接收一個字串,並且回傳反轉過後的字串。(禁止使用內建函式 reverse)
reverse("abcd") 預期回傳值:dcba
reverse("12345aa") 預期回傳值:aa54321
function reverse(str){
let msg = ''
for(let i=str.length-1; i>=0; i--){
msg += str[i]
}
console.log(msg)
}
reverse("abcd")
reverse("12345aa")
寫一個函式 swap,接收一個字串,並且回傳大小寫互換後的字串。
swap("Peter") 預期回傳值:pETER
swap("AbCdE") 預期回傳值:aBcDe
// 參考
function swap(str){
let result = '';
for(let i=0;i<=str.length;i++){
if(str[i] <= 'a' && str[i] <= 'z'){
result += str[i].toLowerCase();
}
if(str[i] >= 'A' && str[i] >= 'Z'){
result += str[i].toUpperCase();
}
}
console.log(result)
}
swap("Peter")
swap("AbCdE")
寫出一個函式 findMin,接收一個陣列並回傳陣列中的最小值。(禁止使用內建函式 sort)
findMin([1, 2, 5, 6, 99, 4, 5]) 預期回傳值:1
findMin([1, 6, 0, 33, 44, 88, -10]) 預期回傳值:-10
// 參考
function findMin(arr){
let minNumber = arr[0];
for(let i = 1; i < arr.length;i++){
if(minNumber > arr[i]){
minNumber = arr[i];
}
}
console.log(minNumber)
}
findMin([1, 2, 5, 6, 99, 4, 5])
findMin([1, 6, 0, 33, 44, 88, -10])
寫一個 function findNthMin,接收一個陣列以及一個數字 n,找出第 n 小的數字。(禁止使用內建函式 sort)
提示:假設我要找出第 2 小的值,我只要先找出最小的值然後再把它刪掉,再重新找一次最小的值,就會是第 2 小的值了。
findNthMin([1, 2, 3, 4, 5], 1) 預期回傳值:1
findNthMin([1, 3, 5, 7, 9], 3) 預期回傳值:5
findNthMin([1, 1, 1, 1, 1], 2) 預期回傳值:1
function findNthMin(arr, n){
}
]]>
分別用 for loop 以及 while 迴圈,印出 1~9。
預期輸出:123456789
// for loop
for(i=1; i<=9; i++){
console.log(i)
}
// while
let i =1
while(i<=9){
console.log(i)
i++
}
寫一個函式叫做 print,接收一個是數字的參數 n,並且印出 1~n。
print(1) 預期輸出:1
print(3) 預期輸出:123
print(9) 預期輸出:123456789
function print(n){
for(let i=1; i<=n;i++){
console.log(i)
}
}
print(10)
寫一個函式 star,接收一個參數 n,並印出 n 個 *
(禁止使用內建函式 repeat)
star(1) 預期輸出:*
star(5) 預期輸出:*****
star(10) 預期輸出:**********
function star(n) {
let msg = ''
for(i=1; i<= n; i++){
msg+='*'
}
console.log(msg)
}
star(4)
寫出一個叫做 star 的 function 並且接受一個參數 n,能回傳 n 個 *
。
star(1) 會回傳 *
star(5) 會回傳 *****
所以 console.log(star(5)) 的預期輸出是:*****
function star(n){
let msg = '';
for(let i=1; i<=n; i++){
msg+= '*'
}
return msg
}
console.log(star(7))
寫一個叫做 isUpperCase 的 functuon,並且接收一個字串,回傳這個字串的第一個字母是否為大寫。
isUpperCase("abcd") 正確回傳值:false
isUpperCase("Abcd") 正確回傳值:true
isUpperCase("ABCD") 正確回傳值:true
isUpperCase("aBCD") 正確回傳值:false
function isUpperCase(str){
let char = str[0]
if(char >= 'A' && char <= 'Z'){
return true
} else {
return false
}
}
console.log(isUpperCase('AAAaAacdd'))
寫一個 function position,接收一個字串並回傳這個字串裡面的第一個大寫字母跟它的 index,若沒有則回傳 -1。
position("abcd") 正確回傳值:-1
position("AbcD") 正確回傳值:A 0
position("abCD") 正確回傳值:C 2
function position(str){
for(i=0; i<= str.length; i++){
if(str[i]>='A'&& str[i]<='Z'){
return str[i] + ' ' + i
}
}
return -1
}
console.log(position())
寫出一個函式 findSmallCount,接收一個陣列跟一個數字 n,回傳有多少個數小於 n。
findSmallCount([1, 2, 3], 2) 預期回傳值:1
findSmallCount([1, 2, 3, 4, 5], 0) 預期回傳值:0
findSmallCount([1, 2, 3, 4], 100) 預期回傳值:4
function findSmallCount(arr, n){
let result = 0
for(let i=0; i<=arr.length;i++){
if(arr[i]<n) result++
}
return result
}
console.log(findSmallCount([1,2,3,4],5))
寫一個函式 findSmallerTotal,接收一個陣列以及數字 n,回傳陣列裡面所有小於 n 的數的總和。
findSmallerTotal([1, 2, 3], 3) 正確回傳值:3
findSmallerTotal([1, 2, 3], 1) 正確回傳值:0
findSmallerTotal([3, 2, 5, 8, 7], 999) 正確回傳值:25
findSmallerTotal([3, 2, 5, 8, 7], 0) 正確回傳值:0
function findSmallerTotal(arr, n){
let result = 0
for(let i=0;i<=arr.length;i++){
if(arr[i]<n) result += arr[i]
}
return result
}
寫一個函式 findAllSmall,接收一個陣列跟一個數字 n,回傳一個裡面有所有小於 n 的數的陣列(需按照原陣列順序)。
findAllSmall([1, 2, 3], 10) 正確回傳值:[1, 2, 3]
findAllSmall([1, 2, 3], 2) 正確回傳值:[1]
findAllSmall([1, 3, 5, 4, 2], 4) 正確回傳值:[1, 3, 2]
function findAllSmall(arr, n){
let result = []
for(let i=0; i<=arr.length; i++){
if(arr[i]<n) result.push(arr[i])
}
return result
}
寫一個 function sum,接收一個陣列並回傳陣列中數字的總和。
sum([1, 2, 3]) 預期回傳值:6
sum([-1, 1, 2, -2, 3, -3]) 預期回傳值:0
function sum(arr){
let result = 0
for(let i=0;i<arr.length;i++){
result += arr[i]
}
return result
}
]]>分別用 for loop 以及 while 迴圈,印出 1~9。
預期輸出:123456789
// for loop
for(i=1; i<=9; i++){
console.log(i)
}
// while
let i =1
while(i<=9){
console.log(i)
i++
}
寫一個函式叫做 print,接收一個是數字的參數 n,並且印出 1~n。
print(1) 預期輸出:1
print(3) 預期輸出:123
print(9) 預期輸出:123456789
function print(n){
for(let i=1; i<=n;i++){
console.log(i)
}
}
print(10)
寫一個函式 star,接收一個參數 n,並印出 n 個 *
(禁止使用內建函式 repeat)
star(1) 預期輸出:*
star(5) 預期輸出:*****
star(10) 預期輸出:**********
function star(n) {
let msg = ''
for(i=1; i<= n; i++){
msg+='*'
}
console.log(msg)
}
star(4)
寫出一個叫做 star 的 function 並且接受一個參數 n,能回傳 n 個 *
。
star(1) 會回傳 *
star(5) 會回傳 *****
所以 console.log(star(5)) 的預期輸出是:*****
function star(n){
let msg = '';
for(let i=1; i<=n; i++){
msg+= '*'
}
return msg
}
console.log(star(7))
寫一個叫做 isUpperCase 的 functuon,並且接收一個字串,回傳這個字串的第一個字母是否為大寫。
isUpperCase("abcd") 正確回傳值:false
isUpperCase("Abcd") 正確回傳值:true
isUpperCase("ABCD") 正確回傳值:true
isUpperCase("aBCD") 正確回傳值:false
function isUpperCase(str){
let char = str[0]
if(char >= 'A' && char <= 'Z'){
return true
} else {
return false
}
}
console.log(isUpperCase('AAAaAacdd'))
寫一個 function position,接收一個字串並回傳這個字串裡面的第一個大寫字母跟它的 index,若沒有則回傳 -1。
position("abcd") 正確回傳值:-1
position("AbcD") 正確回傳值:A 0
position("abCD") 正確回傳值:C 2
function position(str){
for(i=0; i<= str.length; i++){
if(str[i]>='A'&& str[i]<='Z'){
return str[i] + ' ' + i
}
}
return -1
}
console.log(position())
寫出一個函式 findSmallCount,接收一個陣列跟一個數字 n,回傳有多少個數小於 n。
findSmallCount([1, 2, 3], 2) 預期回傳值:1
findSmallCount([1, 2, 3, 4, 5], 0) 預期回傳值:0
findSmallCount([1, 2, 3, 4], 100) 預期回傳值:4
function findSmallCount(arr, n){
let result = 0
for(let i=0; i<=arr.length;i++){
if(arr[i]<n) result++
}
return result
}
console.log(findSmallCount([1,2,3,4],5))
寫一個函式 findSmallerTotal,接收一個陣列以及數字 n,回傳陣列裡面所有小於 n 的數的總和。
findSmallerTotal([1, 2, 3], 3) 正確回傳值:3
findSmallerTotal([1, 2, 3], 1) 正確回傳值:0
findSmallerTotal([3, 2, 5, 8, 7], 999) 正確回傳值:25
findSmallerTotal([3, 2, 5, 8, 7], 0) 正確回傳值:0
function findSmallerTotal(arr, n){
let result = 0
for(let i=0;i<=arr.length;i++){
if(arr[i]<n) result += arr[i]
}
return result
}
寫一個函式 findAllSmall,接收一個陣列跟一個數字 n,回傳一個裡面有所有小於 n 的數的陣列(需按照原陣列順序)。
findAllSmall([1, 2, 3], 10) 正確回傳值:[1, 2, 3]
findAllSmall([1, 2, 3], 2) 正確回傳值:[1]
findAllSmall([1, 3, 5, 4, 2], 4) 正確回傳值:[1, 3, 2]
function findAllSmall(arr, n){
let result = []
for(let i=0; i<=arr.length; i++){
if(arr[i]<n) result.push(arr[i])
}
return result
}
寫一個 function sum,接收一個陣列並回傳陣列中數字的總和。
sum([1, 2, 3]) 預期回傳值:6
sum([-1, 1, 2, -2, 3, -3]) 預期回傳值:0
function sum(arr){
let result = 0
for(let i=0;i<arr.length;i++){
result += arr[i]
}
return result
}
]]>
Javascript 是一個應用於網頁前端的程式語言。
直接去官網下載即可。
// index.js
console.log("Hello World!")
node index.js
,就會印出 Hello World!二進位:由 0 與 1 組成
0100 ( 2^00 + 2^10 + 2^21 + 2^30 ) = 2^2 = 4
1000 = 2^3 = 8
二進位就是把東西往左移後都乘以 2
所以往右移就會變除以 2
左移 <<
右移 >>
位元運算
xor ^
邏輯運算
var box, console.log(box)
→ undefined 宣告了,但沒賦值console.log(box)
→ not defined 連宣告都沒宣告透過 typeof 查詢型態
index,陣列第一個數字從 0 開始
let class = ['A', 'B', 'C']
class.push('D')
console.log('result', class)
ABCD
class.length = 4
let igPosts = ['URL1', 'URL2', 'URL3'] -> 就變貼文串ㄌ
ket = { value }
const card = {
name: 'Lindsay;s card',
job: 'student'
age: 22
}
card.name = 'Lindsay;s card'
(延伸閱讀:從博物館寄物櫃理解變數儲存模型)
var score = 60
if(score >= 60 && score <= 70){
console.log('剛好及格')
}
var score = 60
if(score >= 60){
console.log('pass')
} else {
console.log('fail')
}
var age = 10
if(age >= 65){
console.log('老人')
} else if (age >= 20){
console.log('年輕人')
} else {
console.log('小孩')
}
switch(month){
case 1:
console.log('一月')
break
case 2:
console.log('二月')
break
case 3:
console.log('三月')
break
default:
console.log('hey')
}
if (score >= 60){
msg = 'pass'
} else {
msg = 'fail'
}
->
var msg = score >= 60 ? 'pass' : 'fail'
score 是不是大於等於 60,是的話回傳 pass,不是的話回傳 fail
一直做一樣的事(執行同樣的程式碼),若沒有設定終止條件,就會變無窮迴圈。
迴圈的前世:label、goto ( Javascript 沒有 )
var i = 1
label:
console.log(i)
i++
if(i <= 100){
goto label
}
console.log('i=', i)
var i = 1
do{
console.log(i)
i++
} while(i <= 100)
console,log('i=', i)
var i = 1
while(i <= 100){
console.log(i)
i++
}
for ( 初始值; 終止條件; i 每一圈要做的事情 )
for (var i =1; i <= 5; i++){
console.log(i)
}
y= f(x),y 就是回傳值, f(x) 就是函數,x 就是丟進去的參數
return 後面回傳值不用換行,否則會 undefined
function generateArray(n){
var result = []
for(var i = 1; i<=n; i++){
result.push(i)
}
return resule
}
console.log(generateArray(3))
function transform(arr, transformFunction){ // 接收 arr, transformFunction 兩個參數
var result = []
for(var i=0; i<arr.length; i++){
result.push(transformFunction(arr[i]))
}
return result
}
console.log(
transform([1, 2, 3], function(x){ // 匿名函式
return x+4
})
)
(延伸閱讀:深入探討 JavaScript 中的參數傳遞:call by value 還是 reference?)
只有物件、陣列是可變的
Javascript 是一個應用於網頁前端的程式語言。
直接去官網下載即可。
// index.js
console.log("Hello World!")
node index.js
,就會印出 Hello World!二進位:由 0 與 1 組成
0100 ( 2^00 + 2^10 + 2^21 + 2^30 ) = 2^2 = 4
1000 = 2^3 = 8
二進位就是把東西往左移後都乘以 2
所以往右移就會變除以 2
左移 <<
右移 >>
位元運算
xor ^
邏輯運算
var box, console.log(box)
→ undefined 宣告了,但沒賦值console.log(box)
→ not defined 連宣告都沒宣告透過 typeof 查詢型態
index,陣列第一個數字從 0 開始
let class = ['A', 'B', 'C']
class.push('D')
console.log('result', class)
ABCD
class.length = 4
let igPosts = ['URL1', 'URL2', 'URL3'] -> 就變貼文串ㄌ
ket = { value }
const card = {
name: 'Lindsay;s card',
job: 'student'
age: 22
}
card.name = 'Lindsay;s card'
(延伸閱讀:從博物館寄物櫃理解變數儲存模型)
var score = 60
if(score >= 60 && score <= 70){
console.log('剛好及格')
}
var score = 60
if(score >= 60){
console.log('pass')
} else {
console.log('fail')
}
var age = 10
if(age >= 65){
console.log('老人')
} else if (age >= 20){
console.log('年輕人')
} else {
console.log('小孩')
}
switch(month){
case 1:
console.log('一月')
break
case 2:
console.log('二月')
break
case 3:
console.log('三月')
break
default:
console.log('hey')
}
if (score >= 60){
msg = 'pass'
} else {
msg = 'fail'
}
->
var msg = score >= 60 ? 'pass' : 'fail'
score 是不是大於等於 60,是的話回傳 pass,不是的話回傳 fail
一直做一樣的事(執行同樣的程式碼),若沒有設定終止條件,就會變無窮迴圈。
迴圈的前世:label、goto ( Javascript 沒有 )
var i = 1
label:
console.log(i)
i++
if(i <= 100){
goto label
}
console.log('i=', i)
var i = 1
do{
console.log(i)
i++
} while(i <= 100)
console,log('i=', i)
var i = 1
while(i <= 100){
console.log(i)
i++
}
for ( 初始值; 終止條件; i 每一圈要做的事情 )
for (var i =1; i <= 5; i++){
console.log(i)
}
y= f(x),y 就是回傳值, f(x) 就是函數,x 就是丟進去的參數
return 後面回傳值不用換行,否則會 undefined
function generateArray(n){
var result = []
for(var i = 1; i<=n; i++){
result.push(i)
}
return resule
}
console.log(generateArray(3))
function transform(arr, transformFunction){ // 接收 arr, transformFunction 兩個參數
var result = []
for(var i=0; i<arr.length; i++){
result.push(transformFunction(arr[i]))
}
return result
}
console.log(
transform([1, 2, 3], function(x){ // 匿名函式
return x+4
})
)
(延伸閱讀:深入探討 JavaScript 中的參數傳遞:call by value 還是 reference?)
只有物件、陣列是可變的
簡單來說就是版本控制的軟體,讓我們在多人協作、檔案很多、長時間更動上可以方便清楚地做版本控制。
直接去官網下載即可。
git init:初始化 repo
git status:查詢當前檔案狀態
git add:決定是否把檔案加入版本控制
untracked 沒加入版本控制
staged 已加入版本控制
git commit:新建一個版本(把狀態在 staged 的檔案新建一個版本)/ git commit -m "新建版本名稱" → 新建版本
git commit -am "新建版本名稱" 直接 add + commit 一起做
git log:查看操作的 git 歷史紀錄
.gitignore:版本控制裡不想被看見的檔案
git branch:查看此版本控制內的分支 / git branch 分支名稱 → 新建分支
git checkout:切換分支 / git checkout 欲切換分支名稱 → 切換到該分支
git diff:在 commit(建立一個新版本)前可以看更改了什麼
git merge:這部分我都直接在 github 上操作,實際沒用下指令使用過
pull request:有分支想合併到 master 時發出的請求
git push:將 commit 完版本從本地端推至遠端
git pull:將遠端版本拉至本地端
git clone:將遠端 repo 下載到本地端(但仍是別人的 repo)
fork:將別人的 repo 複製到自己遠端 repo
git hook:目前理解是自動化腳本,許多重複動作寫在這個 hook 裡省去重複動作時間。
可以平行開發,讓版本不互相衝突
開新 branch 時,記得先切回 master(git checkout master)在開新分支,不要在原本的分支再開一個分支,這樣檔案會混亂掉。
]]>簡單來說就是版本控制的軟體,讓我們在多人協作、檔案很多、長時間更動上可以方便清楚地做版本控制。
直接去官網下載即可。
git init:初始化 repo
git status:查詢當前檔案狀態
git add:決定是否把檔案加入版本控制
untracked 沒加入版本控制
staged 已加入版本控制
git commit:新建一個版本(把狀態在 staged 的檔案新建一個版本)/ git commit -m "新建版本名稱" → 新建版本
git commit -am "新建版本名稱" 直接 add + commit 一起做
git log:查看操作的 git 歷史紀錄
.gitignore:版本控制裡不想被看見的檔案
git branch:查看此版本控制內的分支 / git branch 分支名稱 → 新建分支
git checkout:切換分支 / git checkout 欲切換分支名稱 → 切換到該分支
git diff:在 commit(建立一個新版本)前可以看更改了什麼
git merge:這部分我都直接在 github 上操作,實際沒用下指令使用過
pull request:有分支想合併到 master 時發出的請求
git push:將 commit 完版本從本地端推至遠端
git pull:將遠端版本拉至本地端
git clone:將遠端 repo 下載到本地端(但仍是別人的 repo)
fork:將別人的 repo 複製到自己遠端 repo
git hook:目前理解是自動化腳本,許多重複動作寫在這個 hook 裡省去重複動作時間。
可以平行開發,讓版本不互相衝突
開新 branch 時,記得先切回 master(git checkout master)在開新分支,不要在原本的分支再開一個分支,這樣檔案會混亂掉。
]]>一種操縱電腦的方法。
操縱電腦的方法有兩種,一種是 Command Line,另一種是我們習慣使用的圖形化介面 Graphical User Interface(GUI),也就是我們打開電腦看到的桌面,可以自由拖曳的資料夾。
早期電腦沒有圖形化介面操作時,都是以 CLI 透過純文字下指令來操控電腦。
因為下載 git 有預設 gitbash 讓我們可以下 Command Line 指令,之後也會用到 git,所以直接下載 git 比較方便。(for windows)或也可以嘗試 cmder(延伸閱讀:介紹好用工具:Cmder ( 具有 Linux 溫度的 Windows 命令提示字元工具 ) | The Will Will Web)
mac 因為是 linux 系統直接打開 terminal 就可以了。
超簡單!十分鐘打造漂亮又好用的 zsh command line 環境 | by Gary Chu | 財報狗技術部落格 | Medium
心得 iTerm2 + zsh,打造更好的工作環境 « Huli’s Blog
一種操縱電腦的方法。
操縱電腦的方法有兩種,一種是 Command Line,另一種是我們習慣使用的圖形化介面 Graphical User Interface(GUI),也就是我們打開電腦看到的桌面,可以自由拖曳的資料夾。
早期電腦沒有圖形化介面操作時,都是以 CLI 透過純文字下指令來操控電腦。
因為下載 git 有預設 gitbash 讓我們可以下 Command Line 指令,之後也會用到 git,所以直接下載 git 比較方便。(for windows)或也可以嘗試 cmder(延伸閱讀:介紹好用工具:Cmder ( 具有 Linux 溫度的 Windows 命令提示字元工具 ) | The Will Will Web)
mac 因為是 linux 系統直接打開 terminal 就可以了。
超簡單!十分鐘打造漂亮又好用的 zsh command line 環境 | by Gary Chu | 財報狗技術部落格 | Medium
心得 iTerm2 + zsh,打造更好的工作環境 « Huli’s Blog