日期: 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