第1页
JavaScript 與 AngularJS 技術研討會
李柏鋐 (BOHONG LI) 2015 / 07 / 14
第2页
大綱
• JavaScript
• 歷史簡介 • 基礎使用介紹 • 進階功能
• AngularJS
• 基礎介紹 • 進階功能
第3页
JavaScript 是 物件導向程式語言
只是物件的實作方式採用原型繼承
第4页
JavaScript 歷史演進
第5页
JS 歷史
• 由Brendan Eich創造
• 只花10天就將JS做出來,比做期末專案還厲害! • 因為時間很短,所以乾脆做一個可塑性高的語言
• 根本就是到處留洞
• 因為微軟也弄了一個很像的東西-JScript • 歐洲電腦製造商協會(ECMA)要求統一 • 最後產生ECMAScript 標準
第6页
JS 歷史 – cont.
• 大概從IE 5.5開始就支援ECMAScript 3了
• 再之前的就不考古了
• 接著一直想要將亂七八糟的語言特性掰正…
• -> ECMAScript 4 • 結果沒有成功…… 這個版本就消失了
• 妥協後,修改一些功能
• -> ECMAScript 5 橫空出世!! • 這時候大概是Google開始搞傳說中的AJAX時代
(Gmail),各種網頁的都開始流行使用AJAX技術,到 後來FB的出現
第7页
JS 歷史 – cont.
• 因為ECMAScript 5修的還不錯,而且有各種神框 架,舉凡
• jQuery • CommonJS • RequireJS • ExtJS • Ember • React
• 所以JS越來越流行了 • 因為使用的人多反應的聲音多,也就讓
ECMAScript改版的速度加速演進
第8页
JS 歷史 – cont.
• 到了 2015 年 6月ECMAScript 第六版ECMAScript 2015 正式通過,這次的改版將整個JS規格重新 定義
• 加入眾所期望很久的各種功能
• 新的語法: let , const , class, module , for…of … • 新的基本型別: Symbol • 新的資料結構:Typed Array , Map , Set • 新的內建類別: Promise , Proxy , Reflect • 強化原有架構: String , Number , Math , RegExp ,
Object , Array 全員強化
第9页
JS 歷史 – cont.
• 不過由於瀏覽器支援度尚未達標,預計大約半年 後會完全支援
• 微軟於Windows 10的Edge瀏覽器中已經開始支 援
• Visual Studio 2015 也完全支援新的語法
• 但是,請在框架改版之後再用
第10页
JS 歷史 – cont.
敬請期待AngularJS 2.0 (?)
第11页
JavaScript 基本介紹
採用ECMAScript 5
第12页
原生資料型別
•null •undefined •number •boolean •string
第13页
Null
• 代表沒有值 • 空的 • 一個變數可以被指定為null代表他是空的,沒有
值
第14页
Undefined
• 當一個變數被宣告,但還未給任何值的時候就是 undefined
• 你無法對undefined做任何事,當你這麼做的時 候,會噴一個錯誤出來
第15页
Boolean
• 代表著true與 false其中一種值
第16页
Number
• 代表著數字,不管是正數負數整數或是小數 • 用C語言來說這就是個Double雙精確浮點數 • 他實做了IEEE 754標準所規範的64位元數字編碼 • 也當然實做了標準中所定義的NaN
(Not a Number) • 當計算過程中出現了無法成為數字的東西,例如
虛數或是字串,就會產生這個結果 • NaN 不等於NaN 這是規定! • isNaN 他會幫你做隱含轉換……有點雷
第17页
Number – cont. isNaN的問題
• 像是 isNaN(“haha”) 會回傳true • isNaN(“”) 會回傳false • 如果真要測試是否為NaN可用以下這個方式
第18页
Number – cont.
• 當Number 在做位元運算時,會先轉換成32位元 有號整數,運算完再轉回來。
• 明明就有整數還不開來用…
第19页
String
• 所有的字串都是Unicode ,是16 位元 • 但是一些意外的錯估,後來出現了4 bytes代表
一個字的時候…… • 在遇到這種情況時,文字的長度會算錯、取字元
時會拿不到東西
• 像是用String.charAt 取字元的時候
• 這些問題在ECMAScript 2015 有解決
第20页
原生資料型別都有包裹 器(讓他成為物件),除 了null, undefined以外
每個成功的男人背後都有一個偉大的女人
第21页
包裹器 (wrapper)
將原生型別變成物件
第22页
原生型別包裹器
• 與往常一樣,使用new 產生一個instance
第23页
千萬別用包裹器!
用了被雷到我不管
第24页
原生型別包裹器
• 用了包裹器,typeof 的結果都是object了!
• 只要用了金坷垃小麥畝產一千八
• 可是瑞凡,String物件提供好多好棒棒的方法耶
第25页
String wrapper method
• Length • charAt • Indexof • Replace • Slice • Substr • Trim • toLowerCase
• toLocaleUpperCase
第26页
沒關係,你可以直接在 原生型別上呼叫字串物 件才能用的方法
第27页
Call string method on primitive value
• 真是太神奇了 • 其實他幫你做自動型別轉換了…
第28页
Call string method on primitive value 原理
• 運作原理就是:
1. 先幫你將原生型別使用包裹器包 裝
2. 再呼叫物件的方法 3. 再解回原生型別
第29页
其他淺規則 - 隱含轉換
• JS的隱含轉換規則非常詭異,又不好記…… • 尤其在date物件上世界竟然是逆轉的 • 所以建議少用隱含轉換,比較時請使用三個等於
的運算子 • 三個等於代表兩個變數型別要先一樣,再比值
第30页
分號插入機制
• JS 很神你忘記加分號他會替你補……
• 但這補分號的方式又有規則,可能不小心會踩到 雷
• return , throw , break , continue , ++ , -• 以上這幾個東西單獨出現在一行時要多加注意 • 像是++運算子是否前後忘記加變數?
第31页
分號插入機制 – cont.
• 上面提到的return不能單獨在一行是因為JS有個 隱含的分號插入規則是
• 當此行與下一行合在一起的時候不會出現錯誤,就不 會插入分號
• 但是在return , throw , break , continue , ++ , -- 上 是不會看下一行,直接插入分號
第32页
你以為前面那些已經是 JS最雷了嗎?
第33页
不小心就會變成全域變數
• 大家都知道全域變數不好 • 盡量不要用全域變數 • 但是你不小心可能就會宣告了全域變數而不知道
• 忘記加上var是很危險的,雖然程式還是可以動,但 是sum變成了全域變數
第34页
避免忘記加var
• 在ECMAScript 5 中可以使用嚴格模式讓執行環 境檢查出這種忘記加var 的狀況,並丟Error出來
• 使用方式不過在檔案開頭加上一字串
• 其實也可以在每個function第一行加上
第35页
Variable Hoisting 變數提升
• 這點有點像C語言 • 還記得C語言的變數宣告一定要寫在最上面嗎? • JS 也是如此!
第36页
Variable Hoisting – cont.
第37页
也因為有這特性
• 就有人建議將所有變數都先宣告在最上面, • 並且只用一個var 搞定 • 這就是 single var pattern
• 還可以順便寫註解
第38页
變數Scope
• 眼尖的人可以發現,明明宣告在for迴圈內的變 數,卻會被放到前面去
• 因為JS中變數的活動範圍(Scope)是以function 做為分界,這也是為什麼會說function是一級 Class了
第39页
但是 (but)
什麼!!!!
第40页
變數 Scope 例外情形
• 前述的變數Scope有個例外 • 這個例外就發生在例外處理上 • catch的exception變數只在catch中有用 • 但是catch中宣告其他變數則會與前面一樣
第41页
物件與陣列
• 宣告時盡量使用{} 與 [] 的方式,
• 不要用 new Object() , new Array()
第42页
Closures 與 Immediate function
• Closure 指的是 function 中有function • Immediate function 是指function宣告後馬上執
行
第43页
Function 命名的一些現象
• 當把一個具名function 指定給一個變數時,該名 稱只有在該function裡面才可作用
第44页
Function 中的 “this”
• Function 之內使用到的this 會綁定到呼叫者給 傳送給函數的接收者
• 一般呼叫函式時,接收者為綁定到全域 • 全域這個Scope又是綁定到 window 去
(在瀏覽器中) • 所以一般呼叫函式時,函式中的this為window…
第45页
但是用了嚴格模式後又 是不同世界了
Use strict mode is another world
第46页
使用了嚴格模式後的 “this”
• 使用了嚴格模式後,一般呼叫函式this 所綁定的 是undefined
第47页
函式的三種業務
• 在JS中,函式是所謂第一級物件
• Functions are first class object in JS
• 所以Function有各種業務
• 當作一般的函式 • 剛好碰巧可以當作物件的成員方法 • 還可以順便當作建構子使用
第48页
函式的三種業務 - cont.
• 第一種當作一般的函式是一件很正常的事情
• 第二可以當作物件的成員函式純屬意外
• 這只是當你使用物件呼叫函式時,this 就不小心綁定 到了該物件
• 第三種最奇妙,可以當作建構子使用
• 當你在函式前面加上了new,又是不同的事情了
第49页
函式做為建構子?
• 當一個函式被當作建構子呼叫時
• 會產生一個新的物件,然後綁定到函式的this • 最後預設會回傳剛剛所產生的那個this
• 重點
• 自動產生this • 自動回傳this
• 但是
• 你也可以自己改寫回傳值
第50页
函式做為建構子?
第51页
Function 的呼叫
• 函式呼叫分三種
• call • apply • bind
第52页
Function 的呼叫 – cont.
• 這三種功能都有一個特點:
• 可以指定函式被呼叫的時候this是什麼
• Func.call(thisArg[,arg1 [,arg2[, …]]]) • Func.apply(thisArg, argsArray) • Func.bind(thisArg[,arg1 [,arg2[, …]]]);
第53页
Function 的呼叫 – cont.
• 乍看之下call 與 bind 很像
• 但是卻不一樣
• Call 會直接呼叫函式 • Bind 會回傳新的函式
第54页
Function 的呼叫 – cont.
• 所以說 Bind 通常會用在callback function中, 當你的callback function中有使用到this時,你 不會知道到時候你被呼叫的時候,呼叫者是誰, 也就無法決定this 是什麼…就會導致不可預期的 錯誤
• 或許你可以用一些神祕的方法達成功能,像是 • var that = this; • 然後在callback 中都用that 也行
第55页
再講物件導向
• JavaScript是物件導向語言 • 所以理所當然要有封裝、繼承、多型
第56页
物件封裝
• 直接寫物件就好了,根本不用什麼Class
第57页
物件繼承
• 透過神奇prototype 達到繼承
• prototype 是串起整個JS繼承架構的關鍵 • 每個Object都會有prototype
第58页
58
第59页
物件繼承
• 當然,child.prototype 把father new出來後, 你想怎麼改他沒人有意見
第60页
關於prototype
• 將無狀態的method放置prototype中
• 無狀態的method指的是一個method傳給他 固定的參數,不會因為時空背景前後文不同, 而有不同的結果,他只關心他的輸入,與他 要做的事,並產生輸出。
• 因為放置在this當中,每new一個新的物件物 件當中就會有一個一模一樣的函式占用記憶 體空間
• 而且根據測試,在prototype的函式效能比較 好
• 雖然他要從繼承鍊中去找函式
第61页
物件多型
• 在JS中,你愛呼叫什麼方法就呼叫,反正沒有型 別檢查
• 查不到你要呼叫的東西就噴錯誤給你看而已
第62页
62
第63页
結語
• 可能是這些狀況太詭異,所以在新的版本中引進 了class 的保留字,可以用來宣告物件
• 還引入了let 取代var的變數宣告方式
• Let 的 scope比較好預測
第64页
其他JS編寫技巧
• 變數的初始化 • 模組化的作法 • Callback 地獄
第65页
變數初始化
• 使用者呼叫函式可以選擇不傳參數給你
• 會變成undefined
• 也可以多傳很多給你,就當作沒看到
• 但是一切都會記在arguments這個變數中
• 有時候你需要給參數預設值 • 注意
• 當你的參數可以接收空字串或是0 這種會被隱含轉換為 false 的東西時
• 就會發生不可預料的狀況. • 解法:可以判斷是否為undefined • 別讓undefined 有詭異的意義
第66页
模組化
• 使用立即執行函式將模組包起來區隔變數Scope
第67页
Callback 地獄
第68页
解法
• 可以將函式改為遞迴呼叫,或是用promises
第69页
JavaScript 還有很多很 詭異很可怕的東西
其他的請參考 JavaScript Pattern 與 Effective JavaScript :駕馭JavaScript的68個具體做法
第70页
步入AngularJS
第71页
AngularJS 核心概念
• Model-View-Controller 概念 • Data-binding 資料綁定 • Dependency Injection 依賴注入 • Directives 提供強大的html擴充
第72页
MVC
第73页
Data binding
• Controller 中所控制的Model資料可以與View進 行雙向綁定
• 當View資料更新或是Model資料更新時,就可以 馬上反應
第74页
Dependency injection
• 可以方便抽換想要使用的物件 • 方便進行TDD(Test-Driven development)開發 • 需要用到的東西由Module 統一控制,不需要自
己去產生
第75页
Directive
• 擴充HTML的功能 • 像是大家常用到的ion-view 或是 ng-app 皆為
directive • 可將常用功能寫成Directive方便使用
第76页
NG 的應用問題
第77页
1. 不要使用global function做 controller
• 以前可以用global function做為controller ,在 官網可以看到很多例子,但是這個功能是做來給 官網Demo用的
• 請用正統的方式宣告
第78页
一些Controller不能做的事
• 不要在Controller中產生HTML的語法,用 directive達成
• 格式化輸入的資料 建議使用angularJS Form Controller 達成,也就是說一個form 就一個 controller
• 輸出資料的格式變更,使用Filter 功能,如果沒 有你想要的自己寫
• 在Controller中共享狀態,使用Service的功能達 成,因為Service通常都是Singleton
第79页
Module 的問題
• 第一次宣告Module的時候需要進行DI • 第二次開始使用,不能指定DI
第80页
AngualrJS 調用外部函式庫時
• 因為Angular自己有一套運行的生命週期,只有 Angular內的方法NG才會知道,如果是外部的 Library (像是socket.io , 操作DOM, strophe)皆 為外部Library
• 可以將外部Library包裝成NG可以知道的功能, 利用Service 的方式包裝,並且使用$on 或是 $boardcast 進行呼叫
• 如果在Controller中用到外部函式更改了一些東 西最後可以呼叫$apply 讓NG知道有東西被變更 了
第81页
盡量使用NG包裝好的Service
• 礙於NG自己有一套生命週期管理,所以多使用 NG包裝好的Service可以減少不知名的錯誤,像 是資料有更新View不知道
DOM API window setTimeout setInterval window.location console document
NG Service $window $timeout $interval $location $log $document
第82页
AngularJS 的Promise
• 在NG中是使用$q,為promise的簡單實作 • 使用方式:
第83页
AngularJS 的Promise
• 1. 使用$q.defer() 創造一個promise
• Defer : 延遲
• 2. 呼叫了一些非同步未來才會完成的方法後直 接回傳promise
• 3. 在非同步的callback中使用resolve 或是 reject 告訴promise 事情處理的怎麼樣
• Resolve : 事情解決了,並且可以帶參數呼叫 callback
• Reject:剛剛要做的事情被拒絕了,發生了一些問題, 並且附上理由
第84页
AngularJS Promise的使用
• Promise.then( resolveCallbackFn, rejectCallbackFn , notifyFn)
• then會回傳一個新的Promise,所以你可以串接 then
• Promise.then(resolveCallbackFn, …).thne( res olveCallbackFn, …).then…..
第85页
Promise串接的目的
• 有時又Promise執行完進行的resolve不一定是真 的resolve
• 像是$http呼叫WS回傳結果後,說不定其實是有 問題的,像是使用者未登入,但是對$http來說 是呼叫成功,會使用resolve
• 因此可以在第一個then中做資料處理,再傳遞 到下一層的Promise
第86页
RESTful
• 為Representational state transfer 縮寫 • 是一種WS的API定義規則 • 與SOAP或XML-RPC比起來相對簡單 • RESTful 是使用HTTP Vers 與 網址進行API的呼
叫 • 可以方便的定義CRUD
第87页
HTTP Vers
• HTTP 常用的動詞為 GET 與 POST • 而比較少用到的為 PUT 與 DELETE • 在RESTful 中使用這四種動詞
第88页
API 模式
• C create
• POST /shops
• R read
• Read all data
• GET /shops
• Read a specific ID (primary key)
• GET /shops/id
• U update
• PUT /shops/id
• D delete
• Delete /shops/id
第89页
使用ngResource 連接API
• $resource(‘apiurl’)
• $resource(‘http://apps.csie.ntut.edu.tw/shops/:id’)
• 會回傳一個物件包含以下方法
• Get • Save • Query • Remove • Delete
第90页
範例