Giter Club home page Giter Club logo

blog's Introduction

blog's People

Contributors

hackmd-deploy avatar lucifiel0121 avatar

Stargazers

 avatar

Watchers

 avatar  avatar

blog's Issues

Functional Programming in Javascript 練習題 #13-19

Functional Programming in Javascript 練習題 #13-19

http://reactivex.io/learnrx/

以下為有答案的練習紀錄,原題目網站於上方

**Working with Arrays **

The Array is Javascript's only collection type. Arrays are everywhere. We're going to add the five functions to the Array type, and in the process make it much more powerful and useful. As a matter of fact, Array already has the map, filter, and reduce functions! However we're going to reimplement these functions as a learning exercise.

This section will follow a pattern. First we'll solve problems the way you probably learned in school, or on your own by reading other people's code. In other words, we'll transform collections into new collections using loops and statements. Then we'll implement one of the five functions, and then use it to solve the same problem again without the loop. Once we've learned the five functions, you'll learn how to combine them to solve complex problems with very little code. The first two exercises have been completed in advance, but please look them over carefully!



Querying Trees

Exercise 13: Implement concatMap()

Nearly every time we flatten a tree we chain map() and concatAll(). Sometimes, if we're dealing with a tree several levels deep, we'll repeat this combination many times in our code. To save on typing, let's create a concatMap function that's just a map operation, followed by a concatAll.

按照 Exercise 12 的經驗,Map()、concatAll() 時常是一組的,工程師不喜歡做重複的工作,所以就有 concatMap():

  • 第15行 map() 和 第18行 concatAll()成對 簡化成concatMap(),並驗證在 allWords

Exercise 14: Use concatMap() to retrieve id, title, and 150x200 box art url for every video

Let's repeat the exercise we just performed. However this time we'll simplify the code by replacing the map().concatAll() calls with concatMap().

按照慣例,有新的語法就改寫一下之前的練習吧~

有良好的格式規範,就不怕閱讀巢狀結構~

  • concatMap() 的部分是原本的 map()
  • 空格(螢光筆)的部分是原本 concatAll()
  • 綠色 ( ) 是語法提示


Reducing Arrays

[color=#907bf7]Sometimes we need to perform an operation on more than one item in the array at the same time. For example, let's say we need to find the largest integer in an array. We can't use a filter() operation, because it only examines one item at a time. To find the largest integer we need to compare items in the array to each other.

有時候需要同一時間計算 不只一個 的運算,比如說要從一個陣列中尋找最大的整數,這時候就不能用 filter() 運算子,因為它一次只能檢驗一個 值。為了尋找最大的整數,我們需要相互比較陣列裡的元素。

[color=#907bf7]One approach could be to select an item in the array as the assumed largest number (perhaps the first item), and then compare that value to every other item in the array. Each time we come across a number that was larger than our assumed largest number, we'd replace it with the larger value, and continue the process until the entire array was traversed.

有一種方法,
選擇陣列中的一項,作為假設的最大數字(可能是第一項),然後將該值與陣列中的其他項進行比較,當我們遇到一個大於我們假設的最大數字時,我們用最大的值替換它,並繼續該過程,直到遍歷整個陣列。

[color=#907bf7]If we replaced the specific size comparison with a closure, we could write a function that handled the array traversal process for us. At each step our function would apply the closure to the last value and the current value and use the result as the last value the next time. Finally we'd be left with only one value. This process is known as reducing because we reduce many values to a single value.

如果我們用閉包(closure)替換特定的大小的比較,可以為我們編寫一個處理陣列遍歷過程的函式。

每一步,我們的函式都會將閉包應用於最後一個值和當前值,並在下次使用結果作為最後一個值。最後,我們只留下一個值。此過程稱為縮減,因為我們將許多值減少為單個值。


    [1,2,3].reduce( (accumlator,currentValue) => accumlator + currentValue, initialValue) 
    // console : [6]
    // 若沒有給 initialValue ,則用 array[0] 作為 initialValue
    // console : 
    // acc curr
    //  1   2 (= 3)
    //  3   3
    //   6
    // 但是在 Jafar Husain 的教學裡 ,他把 reduce 的回傳複寫加上陣列
    // console: [6]

原生 Array.prototype.reduce() 回傳值 :

若是原生 Array.prototype.reduce(), 一個空陣列,回傳 TypeError

// reduce() without initialValue
[ { x: 22 }, { x: 42 } ].reduce( maxCallback ); // 42
[ { x: 22 }            ].reduce( maxCallback ); // { x: 22 }
[                      ].reduce( maxCallback ); // TypeError

上述原因,會讓使用受限,因為

  1. 不應該讓回傳值 block (如TypeError)
  2. Observable 是一個非同步的集合, Observable.reduce回傳應該是 Observable
    (如同 Jafar Husain: array.reduce 應該回傳也是 array ,不應該設計成 single value)

小總結

  • 如果有一個 array,每次處理 一個 item :
    • 想要把每一個 item 替換/轉換到另一個 array : map( )
    • 想要對 item 寫一個 test function,只留下 test true : filter( )
    • 2維以上要合併的 array : concatAll( )
  • Reduce 至少要有 兩項 才能作用



Exercise 15: Use forEach to find the largest box art

用常用的 forEach 示範一個問題。

Exercise 16: Implement reduce()

理解 how it work 之後,這邊幫你實作好了,關鍵return [accumulatedValue]; 放在 Array 是刻意為之。

Exercise 17: Retrieve the largest rating.

Let's use our new reduce function to isolate the largest value in an array of ratings.

三元運算子:

function() {
	var ratings = [2,3,1,4,5];

	return ratings.reduce( (acc,curr) => acc > curr ? acc : curr  )  
}		


Exercise 18: Retrieve url of the largest boxart

Let's try combining reduce() with map() to reduce multiple boxart objects to a single value: the url of the largest box art.

先使用 reduce 過濾

我們的目標是 url,所以還要再map()



Exercise 19: Reducing with an initial value

Sometimes when we reduce an array, we want the reduced value to be a different type than the items stored in the array. Let's say we have an array of videos and we want to reduce them to a single map where the key is the video id and the value is the video's title.
  • 格式轉換
	{
	    "id": 65432445,
		"title": "The Chamber"
	}

目標 ↓

	[
	 {
		"65432445": "The Chamber"			
	 }
	]

85行可以簡單做到這個:

不過不建議

85行這種方式,會複寫掉原本的值,所以console每次多一筆都是把原來值複寫,稱作可變(mutability)。

如果習慣用這種方式撰寫,很容易在程式的另一個地方(B.accumulatedMap),不小心改變原先這筆資料(A.accumulatedMap)。

如此造成資料錯誤,且無法追蹤(不知道是誰最開始改變的),
這種撰寫風格會使程式:

  1. 提升複雜度
  2. 降低維護性

所以先前的教學強調,每一個屬性都是 return new array

當然,可以自己創一個新的array,讓值賦予新的array (84行)

但是這種調用方式,成本很大,建議使用JS原型鍊的方式調用 Object.creat

  • 簡單提 原型鏈 :
person = { name : "Ashe" }  
//  person 是一個原型物件 (實體)

anotherPerson = Object.create(person);
// anotherPerson 是一個指向 person物件 的參考物件 (沒有實體)

anotherPerson
// console : {}

JSON.stringify( anotherPerson )
// console:  "{}"
// 證明沒有實體

anotherPerson.name
// console : "Ashe"
// 複製一個指向指向 person.name = "Ashe" 的 參考 (copy ref)


如果再變更 person 為person = { name : "Ashe Li" }
因為 person.name 已經被複製,所以不會改到 anotherPerson.name
anotherPerson 依然沒有值。
更詳細可以找其他資料~




用 Object.create() 可以降低成本(memory),用比較好的方法達到成果。
(改為 var clone 是為了可以分辨)

以上這種方式(風格),稱為

Functional Programming

  • 總是獲取資料時創建新的資料,不改變原本資料

參考資料 :
30 天精通 RxJS (02): Functional Programming 基本觀念

Functional Programming in Javascript 練習題 #1~11

asynchronous-javascript-rxjs-observables 的 練習題目

http://reactivex.io/learnrx/

以下為有答案的練習紀錄,原題目網站於上方

**Working with Arrays **

The Array is Javascript's only collection type. Arrays are everywhere. We're going to add the five functions to the Array type, and in the process make it much more powerful and useful. As a matter of fact, Array already has the map, filter, and reduce functions! However we're going to reimplement these functions as a learning exercise.

This section will follow a pattern. First we'll solve problems the way you probably learned in school, or on your own by reading other people's code. In other words, we'll transform collections into new collections using loops and statements. Then we'll implement one of the five functions, and then use it to solve the same problem again without the loop. Once we've learned the five functions, you'll learn how to combine them to solve complex problems with very little code. The first two exercises have been completed in advance, but please look them over carefully!



Traversing an Array

Exercise 1: Print all the names in an array

簡單介紹使用,連答案都不用寫,不過還是練習一下 forEach iterable的特性


Exercise 2: Use forEach to print all the names in an array

Let's repeat the previous exercise using the forEach function.

結果需要練習 forEach , 當做對答案 ...
也是有填寫好了,不懂原理可以去找一下資料

for loop

Array.prototype.forEach()




Projecting Arrays

Exercise 3: Project an array of videos into an array of {id,title} pairs using forEach()

For each video, add a projected {id, title} pair to the videoAndTitlePairs array.

用 forEach 過濾資料,開始有接API的感覺了

array.map() 的版本:


Exercise 4: Implement map()

To make projections easier, let's add a map() function to the Array type. Map accepts the projection function to be applied to each item in the source array, and returns the projected array.

在原有的Array type上, 增加 map 方法
練習了解原生 map 作法的練習

註解部分提供驗證


Exercise 5: Use map() to project an array of videos into an array of {id,title} pairs

Let's repeat the exercise of collecting {id, title} pairs for each video in the newReleases array, but this time we'll use our map function.

前面(Exercise-3)不小心把這題寫掉了,pass




Filtering Arrays

Exercise 6: Use forEach() to collect only those videos with a rating of 5.0

Use forEach() to loop through the videos in the newReleases array and, if a video has a rating of 5.0, add it to the videos array.

過濾掉 rating,只取剛好等於 5.0 的 data


Exercise 7: Implement filter()

To make filtering easier, let's add a filter() function to the Array type. The filter() function accepts a predicate. A predicate is a function that accepts an item in the array, and returns a boolean indicating whether the item should be retained in the new array.

predicateFunction 用於測試條件是否通過,所以只會有 True or False
True : 通過條件,放入回傳的results results.push(itemInArray)


Exercise 8: Chain filter and map to collect the ids of videos that have a rating of 5.0

Exercise 6 換種語法的練習




Querying Trees

Exercise 9: Flatten the movieLists array into an array of video ids

  • 兩層 forEach。

第一層 forEach 取 movieLists.videos,即過濾 movieLists.name 的資料。

第二層 forEach 取值 videos.id ,並 push 到需要回傳的 Array。


Exercise 10: Implement concatAll()

Let's add a concatAll() function to the Array type. The concatAll() function iterates over each sub-array in the array and collects the results in a new, flat array. Notice that the concatAll() function expects each item in the array to be another array.


Exercise 11: Use map() and concatAll() to project and flatten the movieLists into an array of video ids

Hint: use two nested calls to map() and one call to concatAll().

要抓 id, 第一層 map 先抓外層的vidoes

看註解。

注意 concatAll()的對象是 Array of Array,所以要最後執行。

  • 此做法是先 filter 再 concatAll()
  • 有時候可以先 concatAll() 再 filter 取決於使用的函式參數

Learning asynchronous-javascript(observables) begin with Array.

Learning asynchronous-javascript(observables) begin with Array.

HTML5DevConf Jafar Husain, Netflix: Asyncronous JavaScript at Netflix

這篇的系列,主要來自 Jafar Husain ,
以及他在 pluralsight 開立的課程: asynchronous-javascript-rxjs-observables

To begin with , Design Patterns

  • Design Patterns book: Design Patterns: Elements of Reusable Object-Oriented Software: 簡單來說就是常見問題的標準解決方案

  • Jafar Husain 認為,有一個很重要的 design patterns relationships 被遺漏 : Iterator , Observer

  • " There is no line to connected ( for Iterator and Observer ). "

Iterator (Design Patterns)

    var iterator = getNumbers();
    console.log( iterator.next() );
    // console: { value: 1, done : false }
    
    console.log( iterator.next() );
    // console: { value: 2, done : false }
    
    console.log( iterator.next() );
    // console: { value: 3, done : false }
    
    console.log( iterator.next() );
    // console: { done : true }
  • Iterator : consumer can tell producer " done " .

Observer (Design Patterns)

document.addEventListener(
    "mousemove",
    function next(e){ 
        console.log(e)
    }
)

  • Demo on Chrome
  • Event can NOT tell producer " done " , it's Infinity output ( likes Mousemove event )

結論

兩個 Patterns 的作用是一樣的,只是觀察的角度不同

  • 作用是一樣的: produce data
  • 觀察的角度不同
    • Design Patterns: Iterator ( eg. Array.prototype.forEach() ) :
      由 consumer 主動控制 要不要取資料 ( eg. onNext()才會取資料 ),
      而且可以完成 ( done )。

    • Design Patterns: Observer( eg.DOM Event ) :
      producer 會一直丟資料 ( eg. Mousemove event),
      consumer 不能控制,所以也不能告知 producer done

      • 通常是要主動 unhook:
        addEventListener, 然後要記得主動 removeEventListener ,不然如今多數是 SPA,操作一段時間都沒有 unhook,會產生嚴重的 memory leak .




JavaScript ES6 6 tutorial

1. arrow function

    //ES 5
    function(x) { return x + 1; }
    function(x, y) { return x + y; }
    //ES 6
     x  => x + 1; 
    (x, y)  => x + y; 

2. Done.

只要會 arrow function , 因為不想打太多 code

常用 Iterator : ForEach

  [1,2,3].forEach(  x=> console.log(x)  ) 
    //  1
    //  2
    //  3   
  • Why use ForEach?
    async 不能用 Loop ( eg.for i=1;i++;i<10 )
  • Why it works?
    限於 iterator 物件 如 Array.

常用 Iterator : Map

  • map 不修改呼叫它的原陣列本身 ( 回傳新Array )
    • 延伸: pure function
  • 可以用於簡單型別轉換處理
  [1,2,3].map( x=> x+1  )
//   2
//   3
//   4

常用 Iterator : Filter

  • 通常當條件判斷、test function
  • 通過測試才會進入新Array
  [1,2,3].filter( x=> x>1 ) 
//   [2,3]  
  





常用 Iterator : concatAll()

注意: concatAll() 不是原生 js

Array.prototype.concatAll = function() {
   var results = [];
       this.forEach(function(subArray) {
           subArray.forEach( function(item){
         results.push(item);
       });
   });

   return results;
};

  • 不是原生 javascript
  • 將n維array合併為(n-1)維array
  • 注意: 若多維Array存在有空集合,concatAll後的空集合會消失。
  [ [1],[2,3],[],[4] ].concatAll()
//   [1, 2, 3, 4]
  • Demo

  • 應用:



延伸 & diff以下 code:

  • 用 Iterator 風格撰寫,格式十分相似,易於維護及開發。






Introducing Observable

Observable === Collections + Time

Rx => ReactiveX => Reactive Extensions

  • Observables can model
    • Events
      var mouseMove = Observable.fromEvent(element,"mousemove") ;
    • Data requests
    • Animations

特色 :

基本上可以想像和 Promise 類似,但是由其他兩點特色 :

  • Lazy : 如果創建的Observable,沒有被 subscribed 不會執行

  • Cancellable: 如果有大資料的loading/Request,使用者離開頁面,可以終止Http request

  • collection of callbacks 動作如下 :

    • next : 對應 Promise .then() ,接收一個值
    • error : 對應 Promise .catch() ,接收一個錯誤
    • complete : 特有, 指 Marble Diagram 結束那一條線 ,也就是完成訊息
  • 額外的資訊 :

    • Subscription: 記錄訂閱 ( subscribed ) 的東西(註冊 id),需要取消訂閱,如果沒做動作,會有 memory leak 的問題
      *註 : 與 DOM removeEventListener 類似,但通常不會用到,
      因為實際使用 rx.js 裡面的一些API,Subscription 隱含在API實做內。
  • 懶,截圖最開頭提到的影片 HTML5DevConf

Observable 4 種常見策略

..1....2... ...表示時間的流逝

  • 由上到下 由左到右依序加入新的 flat observable
  • 以整個 observable 的 先後順序(order) 不會改變
  • 空的 observable 會消失
  • 依序是 [ {1},{2....3},{}, {4} ],像是有一個暫存queue(佇列)維持順序

- 情境 : 整體的observable (最外層大括號) 像是蛋糕, 內容的{1},{2....3}.... 是切片的小蛋糕,

儘管observable會一直丟蛋糕,但concatAll()唯一關注的是,確保下一個收到切片蛋糕的人都是按照順序的,不會有人插隊。





  • 收到停止條件 {...4} 即停止
  • 特色是不用關注停止條件(如 removeEventListener() ),只關注何時需要設定此停止條件
  • 若 某一個有observable streaming onError 則 此策略會停止,整個observable回傳 onError
  • 若存在TakeUntil,代表一定有終止,比較不會有 memory leak issue.(除非終止條件本身不成立)
    • 情境 : Cancel Button




  • 不考慮 order

  • first in first out

  • 沒有暫存queue(佇列)

    • 情境 : 高速公路車道(1,2,3車道)因事故發生需要封路(第2,3車道),後續來的車輛(1,2,3)先到的先走第一車道。
    • cf. concatAll()會讓第一個車道全部走完才讓第二個車道走,但是第一車道的車是無限的(如mouse event 的監聽),所以 2,3車道會永遠 block 。

動畫 : https://reactive.how/merge





  • 不關注 observable 內的所有資料,如果接受到有新的observable就把之前接受的取消subscript,直接接收最新的
  • {2......3} 因為 3 傳比較慢,即使新到達的 observable 是空值( {} )仍然會被中斷
  • 只保留最新的 observable ,所以不會有 memory leak issue.

- 情境: 連續瘋狂點擊時,不會因為瀏覽器V8 暫存queue 太多而 block 瀏覽器 (因為後面的 queue直接被捨棄)


附註: Async 最常見的問題

1. Race Conditions
2. Memory Leaks
3. Complex State Machines
4. Uncaught Async Errors
  1. 同時有 2 Actions : A、B ,
    • A要先完成執行B ?
    • B要優先於A ?
  2. DOM 事件是否有做過 unhook? 長時間的程式運行,會造成Memory Leaks
  3. 3 .和 4. 合併,基於Javascript特性造成難以追蹤 Async State、bug,即使使用try catch處理,但基本上很難對Async 發揮作用。


播放電影的 Asynchronously

  • 一個實際的例子:
     A. 要求(request)播放電影,需要先確認 authentication id
     B. 加載初始化 (initialized)
  • Race Conditions

    • 每次 A 完成都要確認 B,反之亦然
  • 狀態 State

    • 如果 A(or b) 完成 ,給一個參數,通常是 boolen 表示是否完成,這樣用來追蹤狀態是否完成的參數叫做 狀態 State
    • 狀態會 轉移 ,所以需要 追蹤
      恰巧, Javascript 追蹤 Asynchronously 事件相當複雜,所以有 Asynchronously State 的程式,維護起來相當不容易。
  • Error handler

    • A, B 都有可能發生錯誤,發生錯誤時需要重試(retry),此時需要清除該程式(A, or B)的狀態以避免無法追蹤的錯誤
    • 最好的狀況是能取消 request (A)



小結

DOM : 關注 物件本身 (someSelector) 的 資料流動,collection items(may be memory leak)
observables :關注 整個系統 的 資料流動,streaming (don't collection items)

DOM

document.querySelector('someSelector').addEventListener('event',callback)
    // callback(); do something
document.querySelector('someSelector').removeEventListener('event',callback)

observables

 const scroll = Rx.Observable.fromEvent(someSelector, 'event'); 
 
 event.map( event =>  do something ...  )
      .subscribe()       

Javascript 練習題 #20-24 (Zipping )

Javascript 練習題 #20-24 (Zipping )

http://reactivex.io/learnrx/

以下為有答案的練習紀錄,原題目網站於上方

Working with Arrays

The Array is Javascript's only collection type. Arrays are everywhere. We're going to add the five functions to the Array type, and in the process make it much more powerful and useful. As a matter of fact, Array already has the map, filter, and reduce functions! However we're going to reimplement these functions as a learning exercise.

This section will follow a pattern. First we'll solve problems the way you probably learned in school, or on your own by reading other people's code. In other words, we'll transform collections into new collections using loops and statements. Then we'll implement one of the five functions, and then use it to solve the same problem again without the loop. Once we've learned the five functions, you'll learn how to combine them to solve complex problems with very little code. The first two exercises have been completed in advance, but please look them over carefully!



Querying Trees

Exercise 20: Retrieve the id, title, and smallest box art url for every video.

This is a variation of the problem we solved earlier, where we retrieved the url of the boxart with a width of 150px. This time we'll use reduce() instead of filter() to retrieve the smallest box art in the boxarts array.

一樣是集合前面語法的練習

  • 3個維度Array,只需要兩個 concatMap() + 一個映射預期結果(result)的map()
  • 這裡不用 filter(),用 reduce() ,因為處理 兩個輸入
    somethings.concatMap( something => something.other.
        concatMap( other => other.reduce( whatever... ).
            map( result => 
                ({
                    id: result.id,
                    value : result.value
                })               
            )       
    )

Zipping Arrays

Sometimes we need to combine two arrays by progressively taking an item from each and combining the pair. If you visualize a zipper, where each side is an array, and each tooth is an item, you'll have a good idea of how the zip operation works.

zip rx.js 動畫

  • 可以想像,有一個拉鍊,由兩個 source 合併回一個,而且一定要有一對才可以合併起來
  • 附圖 :

Exercise 21: Combine videos and bookmarks by index

Use a for loop to traverse the videos and bookmarks array at the same time. For each video and bookmark pair, create a {videoId, bookmarkId} pair and add it to the videoIdAndBookmarkIdPairs array.
  • 此例
    • 4 videos
    • 3 bookmarks
    • for loop + array.push()
    • 只有三個結果 (多一個video沒有拉鍊的另一邊可以合併)

Exercise 22: Implement zip

檢驗與實作

Exercise 23: Combine videos and bookmarks by index

看起來很像兩種輸入版本的map(),不過要注意,只取兩個輸入的最小 index size

Exercise 24: Retrieve each video's id, title, middle interesting moment time, and smallest box art url.

先暫存一個變數 把需求抓出來,順便有錯有bug可以抓一下。

  • smallest box art url.

  • middle interesting moment time.

可以直接用兩層 map() 把值取出來,但通常 兩層 map() 會用於考慮

  1. 有順序(order)
  2. 階層(hierarchical)

此時不考慮,因為是可以同時取出,所以處理兩個輸入 最好的方法還是使用 zip() :


movieLists.concatMap( movieList => movieList.videos.concatMap( video => 
        // var samllestBoxArt = video.boxarts.reduce( ( acc , curr ) => ( acc.width * acc.height < curr.width * curr.height ) ? acc : curr );
        // var middleInterestingMoments = video.interestingMoments.filter( interestingMoment => interestingMoment.type === "Middle" );
        Array.zip( 
          video.boxarts.reduce( ( acc , curr ) => ( acc.width * acc.height < curr.width * curr.height ) ? acc : curr ) , 
          video.interestingMoments.filter( interestingMoment => interestingMoment.type === "Middle" ), 
              ( boxart, interestingMoment ) => 
                ({
                  id: video.id,
                  title:  video.title  ,
                  time: interestingMoment.time   ,
                  url:  boxart.url
                }) 
              
        )

  
  )  
)

補一個保留變數的版本

movieLists.concatMap( movieList => movieList.videos.concatMap( video => {
        var samllestBoxArt = video.boxarts.reduce( ( acc , curr ) => ( acc.width * acc.height < curr.width * curr.height ) ? acc : curr );
        var middleInterestingMoments = video.interestingMoments.filter( interestingMoment => interestingMoment.type === "Middle" );
        return Array.zip( 
          samllestBoxArt , 
          middleInterestingMoments, 
              ( boxart, interestingMoment ) => 
                ({
                  id: video.id,
                  title:  video.title  ,
                  time: interestingMoment.time   ,
                  url:  boxart.url
                }) 
              )
    })  
)
 

debugger Asynchronous program

from google

Angular 刻版練習 : JavaScript 題目篇 - 新手 JS 地下城: 1F - 9x9 乘法表

1F - 9x9 乘法表

BOSS 弱點
【特定技術】需使用 JS for 迴圈技巧,裡頭數字不能直接寫在 HTML 上,需使用 JS 印出。

需使用 HTML、CSS、JS 技術

介面需與設計稿一致

下載資源
UI 線上設計稿


解題:
https://angular-f2e.stackblitz.io/

【特定技術】

  • 改寫純樣板為可輸入變數動態產生

    • Array.prototype.push()
  • 思考文字過多時的解決方案 (100x100乘法表內)

    • 練習 : CSS 專家密技
      • 使用 :not() 選擇器
      • 將元素設定垂直居中 (flex: align-items: center)
      • 使用負數的 nth-child 來選擇元素 (這邊是為了用而用 哈哈)
      • 使用 max-height 來建立純 CSS 的捲動軸 (hover的應用)
  • 用到的 Angular 樣板語法

Code 可以 fork 回去玩玩看:
https://stackblitz.com/edit/angular-f2e

  • 2019-03-04 [add] 完整筆記
  • 2019-02-25 [add] 可輸入變數的 9 * 9 -> n * n
  • 2019-02-12 [fix] 沒有 macOS 字體 ,wins 上顯示字型問題

Angular 未整理筆記

如何使用?

  • 文件很多地方都有連結,直接點擊即可。
  • Demo 標籤,代表時間夠可以Demo。
  • 有文章、影片的 reference 盡可能附上。
  • Angular TW 社群 - 線上讀書會系列

建議閱讀順序

  1. VScode
  2. TypeScript
  3. JavaSript MDN Docs導讀 : Array
  4. Angular CLI
  5. Angular




VScode

*預計 Demo 時間 40mins *

請對照 hackmd 一同閱讀 : https://hackmd.io/3uNcseF9TfeiEa0q-VDQXQ
reference 影片 ( 2Hr ) : Angular-TW-forum : VSCode 基本介紹

  • Demo 方便,調整顯示大小 : ctrl +/-

  • Demo 繁體中文:先抓繁中套件 -> F1 ->  Configure Display Language -> "locale":"zh-tw" -> 「手動」重開。

  • Theme 變更 : preview

  • demo icon 變更: 套件 seti-icons -> F1 -> File icon theme

  • 設定 -> 開啟 settings json -> 直接複製 別人(保哥)的設定亦可。

  • 視窗切換

  • demo

    • ctrl+ 數字鍵 :ctrl : 群組切換
    • alt + 數字鍵 : alt : 群組內切換
    • ctrl + tab : 有選單的切換 (很多視窗的預設功能 如 chrome)
    • ctrl + alt + ← or → : 切換當下視窗的群組 (滑鼠拖曳也可)
    • ctrl + \ : 視窗分割
    • ctrl + b : 左側欄收合
    • ctrl + p : 快速搜尋檔名 , :<行數> 可蒐code
  • emmet: 類似 code snippets ,可以快速撰寫程式碼,亦可設定要使用的檔案格式、展開方式

  • 排版格式化工具 prettier :alt + shift + f , 針對 import : alt + shift + o

    格式化的參數可以調整。

  • 快按鍵

    • ### 多重游標操作 - 參照 hackmd

    • ### 內容異動 - 參照 hackmd

      • alt+方向 - 移動行
  • Codelens : 程式碼預覽,重構好用,可以快速查閱 function、參考次數與位置。

  • 重新命名符號(Rename): 參考的function name也會一同變更。

  • intellisense ( 列出成員、參數資訊,快速諮詢和自動完成文字、語法提示 )

  • 更多套件,參考 Github repo





Git in VScode

建議先在自己 repo or 練習用 repo 嘗試

  • EN-官方教學
  • Will 保哥 slide
  • Will 保哥 FB, 影片 - 基本介紹
    • 大綱

      • 基礎命令
      • 右鍵選單講解
      • diff : 右邊可以直接修改
      • (同步) 對應 Source tree : File Status
      • 捨棄變更:不要亂用 可能會把全部資料砍掉
      • conflict 快速解決
      • gitignore 有套件可以快速解決
      • Git Kistory
      • GitLens
    • 1.28.1 改版新增參數 Rebase instead of merge ,
      ( source tree pull 第4個 )

Always rebase when running Sync :
The git.rebaseWhenSync setting will let you configure the Sync command to always use rebase instead of merge when running.





TypeScript

建議先看過影片介紹,(約一篇文章的長度)再閱讀文章,避免有些觀念誤會(因為文章是教材的概念撰寫的)
reference: Angular-TW-fourm : [S02E02][新手村] Typescript 101



  • 懶得看影片,想直接試試:
    • 如果想要快速嘗試 TS : $ npm install -g typescript
      然後輸入 $ tsc yourTSfile.ts 編譯好的 JS會在同層目錄、同名 yourTSfile.js

    • 如果想要查看TS config : $ tsc --init

    • 如果想要TS自動編譯成 JS :

      1. vscode 中 輸入 F1
      2. configure Task
      3. 監看 tsc ,會在根目錄的資料夾 產生 .vscode / tasks.json

    ```
    {
        // See https://go.microsoft.com/fwlink/?LinkId=733558
        // for the documentation about the tasks.json format
        "version": "2.0.0",
        "tasks": [
            {
                "type": "typescript",
                "tsconfig": "tsconfig.json",
                "option": "watch",
                "problemMatcher": [
                    "$tsc-watch"
                ]
            }
        ]
    }
    ```

 然後輸入 `$ tsc -watch` 
 
 ![](https://i.imgur.com/Mb7jpRZ.png)
 
 從圖可以得知,錯誤會直接報錯,但不會讓JS無法編譯。


interface Square {
    kind: "square";
    size: number;
}

interface Rectangle {
    kind: "rectangle";
    width: number;
    height: number;
}

interface Circle {
    kind: "circle";
    radius: number;
}

type Shape = Square | Rectangle | Circle;
// 三種各自獨立的 interface 裡面都有 kind (property),在建立一個額外的 type Shape 形成聯集

function area(s: Shape) {
    // In the following switch statement, the type of s is narrowed in each case clause
    // according to the value of the discriminant property, thus allowing the other properties
    // of that variant to be accessed without a type assertion.
    switch (s.kind) {
        case "square": return s.size * s.size;
        //只會取 square interface 中的物件 (這邊只有size)
        case "rectangle": return s.width * s.height;
        //只會取 rectangle interface 中的物件 (這邊有width, height)
        case "circle": return Math.PI * s.radius * s.radius;
        //只會取 circle interface 中的物件 (這邊只有radius)

    }
}



  • Q : TS 用 class new 出一個實體和直接給值有什麼不一樣?
    • A : class new 的實體 有 method

class Hero {
    constructor(params: any) {
        Object.assign(this,params)
    }
    name: string;
    state: string;

    action(){}
}

const hero = new Hero({ name:'Ashe', state:'active' 
// 可以  hero.action
const heroB: Hero = <Hero>{ name:'Ashe',state:'active' };
// 不可以  heroB.action ,會報錯



總結

interface AType{ }
interface BType{ }

  • type singleType = AType;

  • type unionType = AType | BType;

  • type IntersectionType = AType & BType;

  • type strinType = 'UP' | 'DOWN';

Q : type 和 interface 有甚麼差異?
- A: 兩者都是型別,但interface可以擴充(extends)





JavaSript 基本 : array

reference [S05E01][RxJS系列] JS Array 基本介紹
主要介紹及 習慣 ,如何透過文件找答案。
如果下列關鍵字全部都很熟系,這邊可以跳過。
MDN-Array links

  • 建立 Array 的方法

    var a1 = [1,2,3];
    var a2 = new Array(1,2,3);
    a1   // (3) [1,2,3]
    a2   // (3) [1,2,3]
    
    empty : a2 = new Array(3) 
    a2   // (3) [empty × 3]
    
    console.log(a2.length)   // 3
    
    ... 詳細可以看影片,這邊只是列舉部分告知...真的從基礎開始。
    
  • 迭代陣列 (forEach)

  • Array特性:屬於object,所以可以用object method:

    object.entries(a1),
    object.keys(a1),
    object.values(a1) 
        ... etc 
    
  • Array基本操作方法:

    • push( ) :存入
    • shift( ) : 刪除第一個
    • unshift( ) : 加到陣列前端
    • pop( ) : 取出

    --

    • splice():基本功能 新增/刪除/插入(移除數量=0時)/替換/複製

      • C.F.

    splice 不是 pure function (執行回傳結果會不一樣)
    slice 是 pure function (執行回傳結果都一樣)

  • JS 基礎觀念:

    • 基本型別 : by value ( Boolean、Number、String )
    • 物件 ( array, obj ) 型別 : by reference ( 改一個另一個也會被改,因為指向相同記憶體位址 )
  • Array 複製:

    • splice (): 複製 -> 可以 by value 複製陣列
    • a2 = [... a1] -> 也可以 by value 複製陣列,ES6語法
  • 清除 Array 的方法 :

    var fruits = [1,2,3,4] ;  // (4) [1, 2, 3, 4]
    fruits.length = 0         // 0
    fruits = []               // 0
    
  • Array.from() : 可以把 Notelist 轉成 Array,進行 map / filter 等 array 操作

  • Array.concat() : 合併

    • a3 = [...a1,...a2] ,合併,ES6語法
  • Array.entries() : ie 不支援

  • 條件測試

    every()、some()、includes()

    • Array.every() : 判斷傳入條件,是不是'全部'都符合。只回傳 T / F
    a1 = [2,4,6,8]
    // (4) [2, 4, 6, 8]
    a1.every( x => x < 10)
    // true    
    a1.every( x => x < 5)
    // false    
    
    • Array.some() : 判斷傳入條件,是不是'其中有一'符合。只回傳 T / F

    • Array.includes() : 只回傳 T / F

  • find( )、findIndex()

    • Array.find( ) : 找特定條件。有找到回傳值,沒找到回傳 undefined
    a1 = [ {name:'keven'},{ name:'John' } ]
    //  (2) [{…}, {…}]
    var user = a1.find( x=> x.name === 'John' )
    user
    //  {name: "John"}
    
    • Array.findIndex() : 找特定條件,通常是想要移除Array特定值,找到index可以用splice()移除該值。有找到回傳值,沒找到回傳 undefined
    a1 = [ {name:'keven'},{ name:'John' } ]
    //  (2) [{…}, {…}]
    var user = a1.findIndex( x=> x.name === 'John' )
    user
    //  1
    a1[user]
    //  {name: "John"}
    a1.splice(user,1)
    a1
    // 0:name: "keven" ,length: 1
    
  • Array.fill( ) : 填值

  • Array.filter( ) : 過濾

  • Array.join() : Array轉文字(String)

  • Array.map() : 轉型別,回傳新Array

    forEach + 新Array 可以達到等效

  • Array.reduce() : 分批次計算 eg.

    const array1 = [1,2,3,4]
    
    array1.reduce( (lastValue,currentValue)=>{
        console.log(lastValue,currentValue);
        return lastValue+currentValue;
    },0);
    
    console :  
    0 1
    1 2
    3 3
    6 4
    10
    
  • Array.reverse() : 改變原本的 Array

  • Array.sort() : ASCII 順序或是自訂 function 排序

  • Array.toString()





Angular CLI : Docs 導讀

Angular-TW-forum [S06E01] Angular CLI

這個心得筆記是以線上讀書會的 Angular 影片為主,摘要出一些 key words。
作者Keven也有寫過config檔案設定文章

文件有更新 CLI 7.0
注意自己本地版本與文件是否一致
Angular 7 全新功能探索 (Angular Taiwan 2018)

Github Angular-Cli docs

github docs folder : https://github.com/angular/angular-cli/tree/master/docs/documentation
wiki好讀版 : https://github.com/angular/angular-cli/wiki

  • 環境架設

    • node -vnpm -vcode -v --> vscode
    • 安裝 npm install -g @angular/cli
  • ES5 / ES6 : 可以用,但不如用 Vue,Angular優點全不見。

  • 基本指令 --help 及 docs 閱讀

    • ng --help ,或是 ng [指令] --help 印出參數設定

    • ng new (ng new --help ) : 執行時包含執行 npm install ,可以透過設定改寫成執行 yarn install

    指令範例 : ng new [projectName] --style=sass : 可以直接寫 sass style

  • 基本指令

    • ng new
      • dry-run: 不執行,先列出要建立的檔案
      • force:原本檔案如果存在,直接複寫過去
      • verbose:輸出詳細資訊
      • collection:angular 1.4 之後將之前機制改成 Schematics 的架構(用於產生程式碼範本),可以選擇使用哪個範本,或是擴充成自己公司、自己設計適用的專案範本 (見*註 )
      • inline- xxx : 把檔案(style or template)放在 app.component.ts ,不額外產生另一個檔案
      • view-encapsulation : component 預設的 css scope 要放在哪裡,預設放在component裡
      • routing : 建立routing相關 module
      • prefix : 預設的產生是 app : < app- root >
      • style:可以直接寫 sass/scss/less style,build會直接轉譯成css
      • skip-tests: 不加入測試檔案
      • skip-package-json : 不加入dependencies 檔案

其他需要參閱 docs 連結,影片比較詳細解釋只有ng new,後續列舉常用的。

重點部分用標題 h3 (###)。

  • ng serve : 編譯後啟動 local server (port : 4200) ,參數主要是對 Web server 做設定

    • open:跑完直接開啟瀏覽器

    • 可以指定,如 --port 8080

    • prod

    • aot

  • ng build : build重複執行,會把之前build的檔案覆蓋掉。

    • 底層實作為webpack,調教參數見文檔 -stats-json 說明

    • base-href 不可刪除

    • prod : release用。執行如 AOT、minify、Uglify、tree tracking, etc.

      • ng build --prod : 檔案輸出為 檔名有hash,目的是為了catch更新可以透過每次build不同名稱可以重新抓到新頁面
    • source-map : 用於優化,分析bundle出來的檔案哪個太大(可能是import方式錯誤)

    • deploy-url: 靜態 css,js 放在 cdn 時 ,檔案會指向 url

    • i18n:多國語系

    • extract-css:build時獨立成單個 css

  • ng generate [ Available Schematics ] -- Alias:ng g [ name ] : 自動產生 code & 註冊 module .

    spec 可以不產生
    ng new --skip-tests

    "schematics": {
        // comppnent 不要產生 spec , 影片 42:40s
      "@schematics/angular:component": {
        "spec":false
      },   
    }
    
    • ng generate component [file-name]  ( Alias:ng g c [file-name] ) : 建立 component 範本並更新註冊app.module.ts
  • *註 進階內容:可以自定義寫 CLI 產生的 template :開發出自己的 Schematics 套件 ( 進階內容 - taiking in Angular conf )

  • 檔案結構

    Angular官方docs.img

    CN-Angular-Docs links : https://angular.cn/guide/quickstart#project-file-review

    • package.json :dependencies vs devDependencies : 開發「套件」才需要用到devDependencies,預設安裝dependencies套件區塊

    • 版本號有規範,不贅述

  • augular.json : 此影片重點 (33分)

    • "$schema" :定義 json位置,檢查 json格式

    • newProjectRoot :新版 cli 可以支援同目錄下,多個專案架構,所以需要依賴此設定

    • architect : CLI 7.0 命名改成 target,可以以命令方式執行「指令」。

      • options 參數如檔案輸出位置(outputPath)、assets、styles ,etc.

      ng run [project-name]:[指令] --> ng run demo:build

  • DOM 結構 Docs產生器





Angular Console

Github links

Beginner Friendly : GUI

試用後,還是要查文件找參數說明,不會比下指令快,
但是安裝相依套件可以不用另外找文件,可以考慮搭配使用。

.img- from twitter 10/10 : First Stable Release of Angular Console 

EN - Medium 介紹

Vue 3.0 CLI 有整合類似功能 : vue ui





Angular

reference : udemy
angular-TW-forum



  • Vscode

    • 編輯器本身
      - 控制命令 commit F1 Ctrl + ‵
      - TS 寫 class ,但JS (array)還是要練
      - 元件 : 樣板 - 樣式
      - 同css樣式表隔離
      - Vscode檔案快速開啟 : alt + o 、 ctrl + 右鍵 、 F12
      - Vscode: 選取後直接 [ 會自動補上 eg. [12]
      - vscode: ctrl + e : 檔案搜尋 ctrl + 空白鍵
      - 燈泡 快速鍵: ctrl + .

     - alt + o : 同 comopnent 切換 .html/.ts

    • 選取值,直接輸入 [ 快速完成: [ 值 ]
    • 先設定方法 (.ts / .server ),Ctrl+Space 呼叫IntelliSense
      再選擇綁定事件(.html)
  • Directive

    • @component : selector(html-tag) / style (css) / template(html)
      - ctrl + 空白 : 屬性 ( 有? - 可選)
      - css 預設隔離 (component 隔離) -> 產生 _ngXXXXX-C0 的屬性 ,去對應 css class .css[___ngcontent-c2]
      - 結構型指令 : 會改變生命週期、ng-container 不會產生而外的 dom

Component

推薦 SoC-關注點分離 ( html template 不要寫邏輯。邏輯統一寫在 ts )
  • display var 顯示變數: {{ name }}

    • 值是 component 傳給 => html
  • property binding : <input type="text" [value]="name" [attr.id]="name" />

    • attr vs property 差異
      • property 通常是指dom物件原生的屬性 (f12可以看到原生有哪些property屬性)
      • attr想綁成property binding,可以透過 attr. [attr.date-attr]='binding'
  • event binding : <botton (click)="show()"> alert </botton>

  • two-way binfing (語法糖): <input type="text" [(ngModel)]="name" />

    • 改動會直接寫回去值(此範例為name)
    • 語法糖: 實作 property binding + event binding
        <input type="text" [(ngModel)]="name" />
        
        <input type="text" [ngModel]="name" (ngModelChange)="name=$event"/>
     
     // 語法糖解開用法常用於要增加流程 (如 console.log )
        <input type="text" [ngModel]="name" (ngModelChange)="doSomethingWhenModelChange($event)"  >
    

    樣本參考變數 template

    一個樣本參考變數相同變數只能用一次,除非在 *ngFor 的 scope 生命週期內。

    最常用於 取值 、搭配 *ngIF 。 (不想用ngModel)

    ' # + 變數 ' , 抓到 HTMLElement 本體 (eg. input.value ),可以對 innerHTML修改

     `  <input type="text" #input (keyup.enter)="showValue(input)" /> ` 
    

    display a list ?

    目標必須是 Iterable

    • *ngFor
    • *ngIf
    • *ngSwitch
        <ul>
            <li *ngFor='let item of items' >
                {{item}}
            </li>
        </ul>
    
    
        /* items 必須為 Iterable */ 
    

    裝飾器(Decorators)

    傳值 : 外部傳內部
    @input 搭配 property binding

    @output 類別 : EventEmitter , 搭配 event binding

    this.send.emit('sent somethings')  // 傳值
    (send)="getEvent($event)"  可以取值 
    

    HostBinding: 針對整個 component 的屬性(property)去 binding
    HostListener: 針對整個 component 的事件去 binding (往上層冒泡傳遞)

參考資料  DOM 的事件傳遞機制:捕獲與冒泡

生命週期

1. 因為是 class , 先跑constructor(){}
2. OnChanges
3. OnInit
4. DoCheck
5. AfterContentInit
6. AfterContentChecked
7. AfterViewInit
8. AfterViewChecked
9. OnDestory

CD means Change Detection

不同:
view
content

Directive & Pipe

  • Directive

    • Component

    • Structural Directive

      • *ngIf : 新增 / 移除 DOM
      • *ngFor

        參數 [ boolean: first, last, odd, even, ] , [ number: count, index ]

      <span [ngStyle]=" { 'font-size' : first ? '30px' : ' ' }  "> 
          {{ item.name }} {{ i+1 }} // {{ count }}          
      </span>
      
      //  [ngStyle]=" 'property': expression(可以用 '? t : f' 三元條件運算式)  "
      
      • Observable 在 *ngFor 需要 async
        *ngFor=" let item of ( items | async ) "
      • 星號 * 是 <ng-template[ngIf]=" "> 的語法糖
    • Attribute Directive

  • Pipe

    • i18n

    • 常用於格式轉換 Eg. 西元/民國年, 大寫/小寫, 貨幣, ... ,etc.

    • 同一表單單位 (小數點後n位, 小數點前n位, 財務報表統一格式 ... )

    • 時間、日期單位統一 (類似之前自己寫的顯示jQ)

    • 詳細可用轉換 pipe 種類: https://angular.cn/api/common

      • CurrencyPipe : 貨幣,符合 ISO 4217 之格式,故可以不需額外考量規範。
      • DecimalPipe : 數字格式如千分號,須注意pipe命名DecimalPipe和元件使用時參數命名 {{expression | number }} 不同

       FR 千分號為空格,小數點為逗號   output '1 234,71828'
       EN 千分號為逗號,小數點為'.'    output '1,234.71828'
    




RxJS

reference :
Angular-TW : 一次搞懂 RxJS 與 Observable
Angular-TW : [S05E03] RxJS 基本介紹 - Promise & Iterator

  • Promise MDN

    • Promise 基本語法
     var promise01 = new Promise(function(resolve, reject) { 
     
     ...
     
     });
       
       由於   
       Promise.prototype.then() ,
       Promise.prototype.catch() 
       方法都回傳 promise,它們可以被串接。
    
    
    • 基本 methods
      • Promise.resolve( ) : 成功時執行
      • Promise.reject( ) : 失敗時執行
      • Promise.prototype.then( ) : resovle 時進入判斷條件
      • Promise.prototype.catch( ) : reject 時進入判斷
      • Promise.all( )
      • Promise.prototype.finally( ) : 最後無論resolve, reject,都會進入判斷
      • Promise.race( ) : 多個Promise,有第一個回傳,其他都忽略
    • await / async
  • iterator MDN

    • 有些行為( forEach( )、Map( ) ),本身是可迭代內建物件
    • 可以自行撰寫

以上是基礎知識,不屬於 Rx.JS。為一般使用JS原有的屬性、特性。

以下介紹Rx.JS基本類型

reference Github (code參考,project was generated with angular-cli version 1.0.0-beta.17) https://github.com/chgc/presentation-rxjs

  • Observable

    基本上可以想像和 Promise 類似,但是特別提出區別的地方

    • Lazy : 如果創建的Observable,沒有被 subscribed 不會執行
    • Cancellable: 如果有大資料的loading/Request,使用者離開頁面,可以終止Http request
  • Observer : collection of callbacks, values delivered by the Observable.

    collection of callbacks 動作如下 :

    • next : 對應 Promise .then() ,接收一個值
    • error : 對應 Promise .catch() ,接收一個錯誤
    • complete : 特有, 指 Marble Diagram 結束那一條線 ,也就是完成訊息
  • Subscription: 記錄訂閱(subscribed)的東西(註冊 id),需要取消訂閱,如果沒做動作,會有 memory leak 的問題

  • Operators : 類似 Lodash.js,轉型、過濾

    • Filter : 過濾
    • Combination : concat
    • Transformation : 轉型
    • Utility
    • Error handling : catch,retry
      eg. Map 屬於 Transformation 的一種 Operators,可以把回傳資料轉型
      do 用於記 log ,不會對值有變更
      詳細觀看官方文件。
    
     let button = document.querySelector('button');
     Observable.fromEvent(button, 'click').subscribe(() => console.log('Clicked!'));
    
    // 用 Observable 註冊(subscribe) button 事件(fromEvent),這一條線(Marble Diagram)就是持續可監控的事件。
    
    
    

// tem data //

  • Observable轉Promise : Observable.pipe(toPromise())
  • await Observable.forEach()
     async constructor(){
         await Observable.forEach( data=>{} );
     }
    




[Angular線上讀書會] [S01E07] RxJS - 分享 1

Why Rx.js? instead of promise
Ans:方便封裝(module)、lazy loading

  • map : concatMap / switchMap(eg. Router有關) / mergeMap
    • response 轉 陣列




自行作筆記的區域,沒意義

EN - jQ docs :

https://api.jquery.com/event.data/
http://api.jquery.com/jquery.each/

練習 Q1 :
原生js api 寫 點擊(click)增加class控制畫面。

Ans

DOM
https://medium.com/change-or-die/javascript%E5%88%9D%E5%AD%B8-dom%E5%B8%B8%E7%94%A8%E5%B1%AC%E6%80%A7%E8%88%87%E6%96%B9%E6%B3%95-ef851afdb65a

https://github.com/sulco/angular-developer-roadmap/blob/master/angular-dev-roadmap.png

Functional Programming in Javascript 練習題 #12

http://reactivex.io/learnrx/

以下為有答案的練習紀錄,原題目網站於上方

Querying Trees

Exercise 12: Retrieve id, title, and a 150x200 box art url for every video

You've managed to flatten a tree that's two levels deep, let's try for three! Let's say that instead of a single boxart url on each video, we had a collection of boxart objects, each with a different size and url. Create a query that selects {id, title, boxart} for every video in the movieLists. This time though, the boxart property in the result will be the url of the boxart object with dimensions of 150x200px. Let's see if you can solve this problem with map(), concatAll(), and filter().

There's just more one thing: you can't use indexers. In other words, this is illegal:

var itemInArray = movieLists[0];

Furthermore, you're not allowed to use indexers in any of the remaining exercises unless you're implementing one of the five functions. There is a very good reason for this restriction, and that reason will eventually be explained. For now, you'll simply have to accept it on faith that this restriction serves a purpose. :-)

var movieLists = [
  {
    name: 'Instant Queue',
    videos: [
      {
        id: 70111470,
        title: 'Die Hard',
        boxarts: [
          { width: 150, height: 200, url: 'http://cdn-0.nflximg.com/images/2891/DieHard150.jpg' },
          { width: 200, height: 200, url: 'http://cdn-0.nflximg.com/images/2891/DieHard200.jpg' },
        ],
        url: 'http://api.netflix.com/catalog/titles/movies/70111470',
        rating: 4.0,
        bookmark: [],
      },
      {
        id: 654356453,
        title: 'Bad Boys',
        boxarts: [
          { width: 200, height: 200, url: 'http://cdn-0.nflximg.com/images/2891/BadBoys200.jpg' },
          { width: 150, height: 200, url: 'http://cdn-0.nflximg.com/images/2891/BadBoys150.jpg' },
        ],
        url: 'http://api.netflix.com/catalog/titles/movies/70111470',
        rating: 5.0,
        bookmark: [{ id: 432534, time: 65876586 }],
      },
    ],
  },
  {
    name: 'New Releases',
    videos: [
      {
        id: 65432445,
        title: 'The Chamber',
        boxarts: [
          { width: 150, height: 200, url: 'http://cdn-0.nflximg.com/images/2891/TheChamber150.jpg' },
          { width: 200, height: 200, url: 'http://cdn-0.nflximg.com/images/2891/TheChamber200.jpg' },
        ],
        url: 'http://api.netflix.com/catalog/titles/movies/70111470',
        rating: 4.0,
        bookmark: [],
      },
      {
        id: 675465,
        title: 'Fracture',
        boxarts: [
          { width: 200, height: 200, url: 'http://cdn-0.nflximg.com/images/2891/Fracture200.jpg' },
          { width: 150, height: 200, url: 'http://cdn-0.nflximg.com/images/2891/Fracture150.jpg' },
          { width: 300, height: 200, url: 'http://cdn-0.nflximg.com/images/2891/Fracture300.jpg' },
        ],
        url: 'http://api.netflix.com/catalog/titles/movies/70111470',
        rating: 5.0,
        bookmark: [{ id: 432534, time: 65876586 }],
      },
    ],
  },
];


這一篇比較長,被視作 Key-Exercise。
單獨拉一篇寫筆記,大概翻譯一下問題,不是很精確,大概的意思 :

你已經順利完成 資料樹 (tree) 的二層(維度)深 合併 為 一層 (維度) ,來試試看三層(維度)吧!
你需要創造query ,蒐集 movieLists 裡, 每一個 video 的 {id, title, boxart} 。

其中,boxart 有不同大小和url,目標是一個包含boxart url 的物件,並且條件是 150x200px
請使用 map(), concatAll(), filter() 解決問題

此外 var itemInArray = movieLists[0]; 這種語法(indexers) 不可以使用
接下來的其他問題也是有一樣的 限制條件

其實會限制語法,是因為這邊練習是為了後面的 Rx.js,也是asynchronous programming的特性。

先試試看解這題吧:

  • 蒐集 movieLists 裡, 每一個 video 的 {id, title, boxart}

還差一個boxart的條件,而且每一層裡面都包一個array
[ [somethings], [somethings], [somethings] ]
需要用 concatAll() 合併。

  • 很好,變回來 [ {Objs} ,{Objs} ,{Objs} ]

  • 處理過濾條件

完成!





完成...嗎?

注意到,有個小bug : boxarts:[ url ] ,又是一個二維需要合併。
這時候多懷念var itemInArray = movieLists[0]; .... 輕鬆可以解開,可惜被限制使用。



回想一下,var itemInArray = movieLists[0];是做變數綁定,
把集合內 movieLists,找出 index 的第一個物件 movieLists[0] 綁定在 itemInArray 上,

  • bind a variable to every item in the collection

和某一個函式有點像

[1,2,3].map( x => x+1 )

  • x is every item in that collection




試著實做看看:

之所以造成最後單獨不能解決的 boxarts:[ url ]
是因為先綁定在 video ( 第4行 : some.map ( video => somethings ),scrop 被限縮


movieLists.
map( movieList => 
    movieList.videos.map( video => 
          ({ 
            { someObjs }
          })
      )
).concatAll()

所以我們先過濾好條件:

處理一堆的 array nesting , 三層 -> 一層

加回去 json 格式 (因為如果一開始加,會印不出內容,所以故意現在才加,不影響說明)

補上 id, title。

注意 scope,這種巢狀範圍鏈 (Scope chain) 很容易搞混:

  • video.id, video.title 是在外層 .map( video => somethings ) 的 video 底下取值
  • boxart.url 取值對象是 .filter.map(boxart => somethings)

總結

或許對熟悉的人來說,會有一種「這也要講那麼細?!」的驚訝,不過我理解上,第一次實作確實需要拆到那麼細,希望對閱讀的人也有些幫助。

如果發現任何錯誤,歡迎來訊告知~

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.