日期: 2015/3/19
Front-End Web Developer Nanodegree
https://www.udacity.com/course/nd001
看起來挺不錯的,系列課程!
寫 code 是一件平常沒在寫,就會忘掉的技術。這幾年待在 Rails team 有 F2E 幫忙,前端的東西就忘的差不多了,
特別是 javascript XD
只好重念一次。這次的教材是 Front-End Web Developer Nanodegree 加上 JavaScript: The Good Parts、Eloquent JavaScript 兩本書。
只能說東西不用真的會忘,大概
花了一個月陸陸續續看完這個系列
入門程度
HTML and CSS
JavaScript Basic
Intro to AJAX
HTML5 Canvas
進階程度
OO JavaScript <- 推薦!
JavaScript Design Pattern
Website Performance Optimization
JavaScript Testing 還沒看到課程釋出....
HTML and CSS
===
一開始就用 chrome devtool 教,拿真正的 website 介紹 HTML ,蠻不一樣的
DOM
box model
semantic tags
responsive layout
grid-based layout
bootstrap
最後一集打到人家也太好笑了 XD
專題: mockup to HTML
JavaScript Basic
===
data types
String
Array
truthy/falsy
object 可以用 dot or bracket notation,除了 dot 有一些名稱限制
JSON
flow control
if
for loop
for-in loop
while
annonymous function
除了 var a = function() {} 執行時不會將 function() 宣告放到最前面
而 function a() { } 會放到最前面
object and encapsulation
Intro to jQuery
===
selectors
by tag, class, id, filters
find 底下所有都找
children 只找下一層
traversing
parent
parents
first
last
prev
next
DOM manipulation
addClass
removeClass
toggleClass
css
attr
text
html
val
append
prepend
insertBefore
insertAfter
remove
each
$(document).ready(handler) 或 $(handler)
專題: 履歷 html 用 js 妝點!
OO JavaScript
===
這一集換 hacker reactor 錄,風格丕變! XD
Lexical Scope: 可以 access 的 variable 範圍
global scope
function 創造新的 scope
少了 var 也會產生 global variable
if, while 不會產生 scope
Execution context 是正在執行的 code 範圍
每 call function 就會進到新的 execution context
影響 this 變數 (?)
closure
一些測驗考蠻仔細的
p.s. why use ( function(){ … } )()
例如 coffee script 很愛,連 switch statement, constructor 都再包一層 (function(){} )()
因為裡面的 var 變數就不會跑到外面去!!! 也不會不小心覆蓋掉外面的變數
var a = 2;
var b = 2;
(function(){ var b = 0; a+b; })(); // 這是 2
這裡 b 還是 2
this keyword
parameter this
先介紹了五個誤解!
current object that invoke the function at call time
找 .dot 的那個 obj at call time
不一定是定義 function 的那個 object literal
例如 obj.fn()
如果只有 fn(),那 this 會是 global object
.call 可以蓋掉 current obj,例如 fn.call(obj2)
(終於搞懂什麼是 call 跟 apply 了!!!)
小心當作 callback 的 function,它的 this 仍是 global object
例如 SetTimeout( r.method, 1000 )
method function 裡面的 this 會是 global object
解法是再包一層 annynous function
setTimeout( function(){
r.method(g, b)
}, 1000)
這時候 method function 裡面的 this 才會是 r
new r.method(r,b) 則會每次產生的新的 object 變成 this
prototype chains
var copy_obj = extend({}, from_obj) // jquery 有這方式,等於沒有 chain
var new_obj = Object.create(fallback_obj) // or called prototype_obj
constructor property 是建構這個物件的 function object
所有 object 都 delegate 到 Object.prototype
除了 Array 或有自訂 protytype 的 object
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create
ps. 每個 constructor function 都有 prototype,同一個 contructor 建構出來的 object 共用同一個 prototype (from Eloquent Javascript 一書)
ps. new 的作用就是呼叫 Constructor Function: new ConstructorFunction()
object decorator pattern 新增 functionality 到已有的 object 上
code reuse and DRY
a car game example
extract to a function
decorator function
var carlike = function(obj, loc) {
obj.loc = loc;
obj.move = function() { obj.loc++; }; // 但是這樣每次都會重建不同的 function object。但我們又不希望把他弄成 global varaible
return obj;
};
var amy = carlike({}, 1)
functional classes
a class is construct 慣例用大寫
var Car = function(loc){
var obj = { loc: loc };
obj.move = move;
return obj;
}
var move = function() {
this.loc++;
} // 放外面可以避免放 Car 裡面每次建不同的 function object
但是 move 還是變成 global 了,一招是用之前教的 extend:
var Car = function(loc) {
var obj = { loc: loc };
extend(obj, Car.methods);
return obj;
}
Car.methods = {
move: function() { ... }
}
var amy = Car(1)
prototypal classes
如何改進 performance? 用 prototype chain 來共用 shared prototype object,而不需要 extend
var Car = function(loc) {
var obj = Object.create( Car.methods );
obj.loc = loc;
return obj;
}
Car.methods = {
move: function() { ... }
}
語言慣例的名稱是用 prototype (預設的 object 用這個名字),
事實上他跟 methods 只是名稱而已,代表一個普通的 object 而已...
他之所以會有 fallover 機制完全是因為 Object.create 的關係。
var Car = function(loc) {
var obj = Object.create( Car.prototype );
obj.loc = loc;
return obj;
}
Car.prototype.move = function() { ... }
JS 用 prototype 這個名稱也是讓學習容易搞混啊
Car.prototype.constructor 會回傳 Car
var amy = Car(1)
amy.constructor 也回傳 Car,因為 fallover 機制他等於 amy.__proto__.constructor
amy instanceof Car
p.s. __proto__ 是透過 Object.create 自動建立出來的反向連結!
pseudoclassical patterns
上述可以再用 new 語法簡化,變成 Constructor mode
var Cat = function(loc) {
this.loc = loc
}
var amy = new Car(9);
superclass and subclasses (functional pattern 的方式)
var Car = function(loc) {
val obj = { loc: loc }
obj.move = function() { .. }
return obj;
}
var Van = function(loc) {
var obj = Car(loc);
obj.grab = function() { ... }
}
var amy = Van(1)
pseduoclassical subclasses (另一種比較的常見做 subclass)
var zed = new Car(3)
var amy = new Van(9) // Van 是 subclass
var Car = function(loc) {
this.loc = loc;
}
Car.prototype.move = function() {
this.loc++;
}
var Van = function(loc) {
Car.call(this, loc); // 呼叫 Car 的 constructor
}
Van.prototype = Object.create( Car.prototype ); // 換掉本來的 prototype。應該等同於 new Car()
Van.prototype.constructor = Van; // 少了這行答案 amy.constructor 會是 Car
Van.prototype.grab = function() {}
HTML5 Canvas
===
目標:
1.作一個 meme 應用
2. 以 pixel 為單位重繪
專題: 做一個 Arcade Game https://www.youtube.com/watch?v=p2JhGrrwLuQ&feature=youtu.be
Intro to AJAX
====
intro to ajax
facebook and twitter timeline example: it's JSON including HTML
intro to jQuery AJAX, $.ajax
example project:
Google Streetview
wikipedia
NY Times
append 第三方圖片,用 img src (但這不算是 ajax)
申請 http://developer.nytimes.com/ api key
練習 http://developer.nytimes.com/docs/read/article_search_api_v2
$.getJSON(url, function(data){ ... } )
$.getJSON(url, function(data){ ... } ).error(function(e){...} )
CORS or JSON-P,要看 server-side 支援哪一種
$.ajax({
url:,
dataType: "jsonp",
success: function(data) {
...
clearTimeout(wikiRequestTimeout);
}
})
JSONP 沒有 ajax error handling! 只好設定一個 timeout 顯示錯誤訊息
var wikiRequestTimeout = setTimeout(function(){
....append error text
}, 8000);
debugging with chrome devtool
1. request generic HTML 2. request unique HTML
3. render generic HTML 4. render unique HTML
JavaScript Design Patterns
====
Lesson 1: Chanding Expectations
----
example app: a cat clicker
放一隻貓計數器
requirements change all the time!
改新增兩隻貓!
closure 和 event listener 問題:
https://www.udacity.com/admin/tools/content-editor#!/c-ud989/l-3417188540/m-3480348671
https://www.udacity.com/course/viewer#!/c-ud989/l-3417188540/m-3480348671
// 這樣不行,每次的 num 都會一樣
var num = nums[i];
elem.addEventListener('click', function() {
alert(num); // 這會發生在 click 的當下(scope不同了),那個當下 num 已經是最後的值
});
// 需要改成這樣:
elem.addEventListener('click', (function(numCopy) {
return function() {
alert(numCopy)
}; // 讓每個 click 的 function 都不一樣
})(num));
改五隻貓! 姓名列表,點名字才顯示貓的資料。
Spaghetti Code 需要 organize code
用電話線路來比喻 ---> 用 hub 來 organize
MVO: Model, Octopus, View
Model: data
View: UI
Octopus: 銜接兩者,可能是 C, VM, P, *,目的都是拆開 M 和 V
MVO example 1:
https://github.com/udacity/ud989-pizzamvo
M 和 V 不會直接溝通,而是透過 Octopus
MVO example 2 and two exercises:
https://github.com/udacity/ud989-retain
1. 改成 reverse order => 在 Octopus 層做
2. 加上 date
Lesson 2: Refactoring with Separation of Concerns
----
plan first: 回頭看 plan cat clicker
建議拆成兩個 views: name list 和 cat area
重構前一個 lesson 的 andy (novice) code: https://github.com/udacity/ud989-cat-clicker-andy
re-write the cat clicker
review the premium solution
再加需求,新增 Admin mode 有個表單可以修改目前的 Cat
refactor code: 改 code 不影響功能
練習重構 https://github.com/udacity/ud989-school-attendance
不過看完 bad code 後,建議 burn it! 重寫!!
F2E interviews about refactors
這裡教你不需要用 MVC framework 就可學 Sepration of Concerns
練習重構之前的 Resume Project
Lesson 3: Using an Organization Library
----
MVC: Model View Controller
MVVM: Model View ViewModel
MVP: Model View Presenter
都是 MVO 變形而已
library v.s. framework
organizational library i.e. application organization: MVC, MVVM
organizational framweork == organizational library
不需要重新發明輪子
Fundamental Organizational Concepts
Model
Collections: smart array contains model data
ViewModel or Controller
Views
Routers: track status of application
不管用哪一個 framework,基本觀念都很像
Knockout JS: organizational library
MVVM
ViewModel - similar to Octopus
Declarative bindings
Automatic UI refresh (two-way binding)
Dependency Tracking (models can depend on other models)
example: http://jsfiddle.net/rniemeyer/3Lqsx/
用 var your_model = ko.observable("your value") 包裝處理 model
your_model() # read
your_molde(new_value) # write
自己找 documentation 回答 Observable Arrays 問題
jQuery 本身是 function 也是 object 可以有其他 property
練習 https://github.com/udacity/ud989-cat-clicker-ko-starter 開始練 ko
Computed Observables: ko.computed( function() { ... } )
Control flow: foreach binding, with binding
拆 cat model 出來
Lesson 4: Learning a New Codebase
----
接手 existing codebase: 先了解用什麼 framework 和 libraries
http://todomvc.com/ 不用害怕隨時學習新 framework
範例研究 https://github.com/udacity/ud989-todo-app
有 Underscore, Backbone 和 Bower
研究 Backbone,注意 Backbone 不是標準的 MVC 也不是 MVVM, MVP
接手 legacy app 就該 follow 它本來的 coding style, framework, libraries,保持 consistency,而不是用你自己的 style
IIFEs (Immediate-Invoked Function Expressions)
http://en.wikipedia.org/wiki/Immediately-invoked_function_expression
避免 global scope 污染
用 git
功能修改: 加上 "--Done" 在 todo 後面
只要改 html 檔案即可,因為 template 即 html 檔案
新增額外的 UI: 新增 edit button
加上 template 和參考本來的 dblclick event
看文件和 google
新增功能: priority button
More ideas:
priority status 當 new todo
filter or sort by priority status
priority two levels
recycle bin for recover deleted items
add colors to todo
add labels for filters or sorts
No magic, be detective
Write code everyday
專題: Neighborhood Map
Website Performance Optimization
===
這一 course 是 ruby 界大神,目前在 google 的 Ilya Grigorik 錄的
Lesson 0 - Getting Up and Running
----
Lesson 1 - The Critical Rendering Path
-----
Lesson 2 - Optimizing the CRP
-----
專題: Website Performance Optimization portfolio project
JavaScript Testing
====
lesson1: 很基本的 unit test 介紹
lesson2: 真正開始介紹 Jasmine,以及練習 TDD: Red-Green-Refactor
Jasmine:
http://jasmine.github.io/2.2/introduction.html
git clone https://github.com/udacity/ud549
使用 SpecRunner HTML
describe 只是組織 code 用途
expect(...).toBe(...);
toBe 就是比較 ===
expect(...).not.toBe(...)
練習 AddressBook 和 Contact models
expect(...).not.toBeDefined()
Array.prototype.splice()
beforeEach(fucntion(){...})
async test:
例如使用 set_timeout 或 API call
使用 done() 當作 callback 告訴 jasmine 跑完了
it 的第二參數 function 多一個參數 done
專題: P6: Feed Reader Testing