Javascript Array 筆記

方法範例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
// push
var arr = [1, 2, 3];
var result = arr.push(4); // result: 4, arr: [1, 2, 3, 4]

// pop
var arr = [1, 2, 3];
var result = arr.pop(); // result: 3, arr: [1, 2]

// length
var arr = [1, 2];
arr.length; // 2

// unshift
var arr = [1, 2, 3];
var result = arr.unshift(0); // result: 4, arr: [0, 1, 2, 3]

// shift
var arr = [1, 2, 3];
var result = arr.shift(); // result: 1, arr: [2, 3]

// splice 拼接
// Array.splice(start_index, remove_num, element01, element02...)
var arr = [1, 2, 3, 4, 5];
var result01 = arr.splice(2, 1, 6); // result01: [3], arr: [1, 2, 6, 4, 5]
var arr = [1, 2, 3, 4, 5];
var result02 = arr.splice(2, 0, 6); // result02: [], arr: [1, 2, 6, 3, 5, 6]
// 沒移除元素會放在該 index 元素會被往後推
var arr = [1, 2, 3, 4, 5];
var result03 = arr.splice(2, 0, 6, 7, 8) // result03: [], arr: [1, 2, 6, 7, 8, 3, 4, 5]

// slice 切片
var arr = [1, 2, 3, 4, 5];
var result01 = arr.slice(1, 3); // result01: [2, 3], arr: [1, 2, 3, 4, 5]
var arr = [1, 2, 3, 4, 5];
var result02 = arr.slice(-2); // result02: [4, 5], arr: [1, 2, 3, 4, 5]
var arr = [1, 2, 3, 4, 5];
var result03 = arr.slice(-2, 0); // result03: [], arr: [1, 2, 3, 4, 5]
var arr = [1, 2, 3, 4, 5];
var result04 = arr.slice(0); // result04: [1, 2, 3, 4, 5], arr: [1, 2, 3, 4, 5]

// indexOf
var arr = [1, 2, 3, 4, 5];
var result01 = arr.indexOf(3); // result01: 2
var arr = ['a', 'ab', 'abc', 'abcd'];
var result02 = arr.indexOf('a'); // result02: 0
var result03 = arr.indexOf('b'); // result03: -1
var result04 = arr.indexOf('ab'); // result04: 1

// lastIndexOf
var arr = [1, 2, 3, 2, 1];
var result01 = arr.lastIndexOf(1); // result01: 4
var arr = ['a', 'ab', 'abc', 'ab', 'a'];
var result02 = arr.lastIndexOf('a'); // result02: 4
var result03 = arr.lastIndexOf('b'); // result03: -1
var result04 = arr.lastIndexOf('ab'); // result04: 3

// some 陣列是否有元素符合測試
var arr = [1, 2, 3, 4, 5];
var result01 = arr.some(function (element, index, array) {
return element > 3
}); // result01: true
var result02 = arr.some(element => element > 5); // result02: false

// every 陣列中是否所有元素都符合測試
var arr = [1, 2, 3, 4, 5];
var result01 = arr.every(function (element, index, array) {
return element > 3
}); // result01: false
var result02 = arr.every(element => element < 6); // result02: true

// join 串聯成字串
var arr = [1, 2, 3, 4, 5];
var result = arr.join(','); // result: "1,2,3,4,5"

// sort 由小排到大
var arr = [5, 4, 3, 2, 1];
var result = arr.sort(); // result: [1, 2, 3, 4, 5], arr: [1, 2, 3, 4, 5]
var arr = ['c', 'b', 'a', 0];
var result = arr.sort(); // result: [0, 'a', 'b', 'c'], arr: [0, 'a', 'b', 'c']

// reverse 由大排到小
var arr = [1, 2, 3, 4, 5];
var result = arr.reverse(); // result: [5, 4, 3, 2, 1], arr: [5, 4, 3, 2, 1]
var arr = [0, 'a', 'b', 'c'];
var result = arr.reverse(); // result: ['c', 'b', 'a', 0], arr: ['c', 'b', 'a', 0]

// concat 組合並回傳一個新的陣列(flat element)
var a = [1, 2];
var b = [3, 4];
var c = a.concat(b); // a: [1, 2], b: [3, 4], c: [1, 2, 3, 4]
var d = [...a, ...b]; // a: [1, 2], b: [3, 4], d: [1, 2, 3, 4]
var e = a.concat(0, [3, 4]); // e: [1, 2, 0, 3, 4]

// forEach
var arr = [1, 2, 3, 4, 5];
arr.forEach(function (element, index, array) {
console.log(element, index, array);
});
// 1, 0, [1, 2, 3, 4, 5]
// 2, 1, [1, 2, 3, 4, 5]
// 3, 2, [1, 2, 3, 4, 5]
// 4, 3, [1, 2, 3, 4, 5]
// 5, 4, [1, 2, 3, 4, 5]
// 注意: 例外無法阻止 forEach 停止

// map 遍歷所有元素至參數 callback 然後回傳一個新的陣列
var arr = [1, 2, 3, 4, 5];
var result01 = arr.map(function (element) {
return element + 10;
}); // arr: [1, 2, 3, 4, 5], result01: [ 11, 12, 13, 14, 15 ]
var arr = [1, 4, 9];
var result02 = arr.map(Math.sqrt); // arr: [1, 4, 6], result02: [1, 2 ,3]

// filter 過濾元素,產生新陣列
var arr = [1, 2, 3];
var result = arr.filter(function (element) {
return element > 2;
}); // arr: [1, 2, 3], result: [3]

// reduce 從左至右當作累加器把陣列變成單值
var arr = [1, 2, 3, 4, 5];
var result = arr.reduce(function (previous, current, currentIndex, array) {
return previous + current;
}, 100); // result: 115

// reduceRight
var arr = ['ab', 'bc', 'de'];
var result = arr.reduceRight(function (pre, cur, index, arr) {
return pre + cur;
}, 'I am initial:'); // result: "I am initial:debcab"

// 其他補充
var a; // a: undefined
var b = a += 2; // a: NaN, b: NaN => undefined += 2 => NaN

var a = null;
var b = a += 2; // a:2, b: 2

Array.forEach 額外補充

根據 MDN 的定義 arr.forEach(callback[, thisArg]) 當我們要在 forEach 的匿名函數中使用 this 我們可以透過 thisArg 來設定。
如果不設定(undefined, null)或者不用 var self = this; 的方式保留 context,那麼預設會是指向 global

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var sum = 100;
function Counter () {
this.sum = 0;
}

Counter.prototype.add = function (arr) {
arr.forEach(function (el, i, arr) {
this.sum += el;
})
};

var o = new Counter();
o.add([1, 2, 3]);
console.log(o.sum); // 0
console.log(sum); // 106

在 Chrome 或者 Firefox console 底下執行的確會執向 global,但是在 nodejs v5.6.0 底下結果卻是

1
2
console.log(o.sum); // 0
console.log(sum); // 100

要注意。

正確的範例如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function Counter () {
this.sum = 0;
}

Counter.prototype.add = function (arr) {
arr.forEach(function (el, i, arr) {
this.sum += el;
}, this); // <-- here this "thisArg"
}

var o = new Counter();
o.add([1, 2, 3]);
console.log(o.sum); // 6
console.log(sum); // undefined

callback methods

  • filter (has thisArg)
  • some (has thisArg)
  • every (has thisArg)
  • forEach (has thisArg)
  • map (has thisArg)
  • reduce
  • reduceRight

Chrome Dev tool 筆記

Element Panel

  • ⌥⌘I 開啟 Dev Tool

選取元素的方式

  • 對元素點右鍵 -> Inspect
  • 開啟 Dev Tool -> 點擊 Dev Panel 左上角 bar 的箭頭 ICON -> 選取元素
  • ⌘⇧C -> 選取

編輯樣式

  • 選定一個 Element 之後右邊 panel 會顯示該 Element 之樣式
  • 開關樣式
  • 新增或刪除樣式
  • 右上角 -> Change state(hover, active, focus, visited)
  • Computed -> 觀察 box model
  • 點擊連結切換到 Source
  • Shift + 點擊 CSS rule 的顏色會轉換 e.g. hex to rgb
  • 編輯樣式時,選取某個字串 ->Command+D會把一樣的都選起來

Source Panel

  • 進入 Source panel ⌘S 可以暫時編輯檔案並存到瀏覽器的 Storage
  • 右鍵 -> Local Modifications 可以檢視歷史紀錄

Console

1
2
3
4
5
6
7
8
9
10
11
12
13
console.log();
console.assert(false, 'Information'); // 錯了就噴第二個參數
console.count('go'); // go: 1
console.count('go'); // go: 2
console.log("document body: %O", document.body);

console.group("Authenticating user '%s'", user);
console.log("User authenticated");
console.groupEnd();

console.log('%c Hello', 'color: orange;'); // %c 使用 css
console.log("%O ", document.body); // %O Javascript Object
console.log("%O ", document.body); // %o DOM

詳細 Console API

  • 學會查看 Error,切換到 Source
  • 在 Source panel 下 ESC 開啟第二層 Console
1
2
3
4
5
6
$('selector') // 稱為 blind
// 如果載入 jQuery 預設的 blind 會被覆寫
// 回傳的是一個陣列
inspect($('#title')) // 選取元素並切換到 Element Panel
$0 // 當前選取的 Element
$1 // 上一個
  • Source panel 右上角的 Pause on 按鈕打開的話,下次噴錯就會暫停
  • Source panel 左下角的 {} 按鈕可以把 minifed 檔案轉換成較易讀的格式

Local Storage

  • 切換到 Resource panel

Network panel

  • Refresh 之後會記錄每個 Request
  • + Refresh 鍵強制全部重載
  • Size = Transfer size
  • Content = Actual size
  • 最底下的 Bar 有總和
  • Waterfall 裡面淺色的部分代表發出 request回應即開始傳輸資料的時間
  • 實心的部分代表開始下載資料
  • 顏色的意義
    • HTML 藍色
    • JS 橘色
    • CSS 綠色
    • 圖片 紫色
    • 右邊垂直的藍色線代表 DOM loaded 意為瀏覽器解析完畢 HTML to DOM
    • 右邊垂直紅色線則表示圖片等資源下載完畢
  • CSS 放在 JS 之前

Timeline

  • 顏色的意義
    • Loading 藍色
    • 執行 Script 黃色
    • Rendering 紫色
    • Painting 綠色
  • Size vs Content

從<琅琊榜>學 Redux

前言

這篇文章希望從另外一個角度來看關於 Redux 的機制與運用,在網路上各式的教學文章中值得先推薦的自然是官方教學
如果英文不是很好的可以參考繁體中文版。這是小弟認為要學習 Redux 必讀的文件。另外還有A cartoon intro to redux也是值得一讀的好文可以加深記憶。

接著就讓我們開始吧,當然最後如果有任何錯誤,也歡迎您的指教。

繼續閱讀

NodeJS path

範例筆記

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40

/**
* 詳細教學
* http://www.tutorialspoint.com/nodejs/nodejs_path_module.htm
*/

// 正常化
path.normalize('/1/../2'); // => /2

// 把所有路徑整合在一起並且正常化
path.join('a', 'b'); // =>'a/b'
path.join('a', './b'); // => a/b'
path.join('a', '/b'); // =>'a/b'
path.join('/1', '/2/3', '../4'); // => /1/2/4


// 從第一個路徑,照著後面切換最後回傳絕對路徑
path.resolve('/from', '/to/path1', '/to/path2'); // => /to/path2
path.isAbsolute('/'); // => true

// 從 from 到 to 的相對路徑
path.relative('..', './A/B'); // => [project]/A/B

// 回傳該檔案所在的目錄
path.dirname('node_modules/bin/webpack'); // => node_modules/bin
path.dirname('./node_modules/bin/webpack'); // => ./node_modules/bin

// 回傳路徑最後的部分,包含副檔名
path.basename('node_modules/bin/webpack'); // => webpack
path.basename('/1/2/3.js'); // => 3.js

// 只取副檔名 + .
path.extname('/1/2/3.js'); // => .js

// 將路徑解析成物件
path.parse('/1/2/3.js'); // =>

// 從物件轉成字串
path.format({ root: '/', dir: '/1/2', base: '3.js', ext: '.js', name: '3' }); // => /1/2/3.js

React Native Push Notifications

在 React Native 中的 Push Notifications

React Native 官方在 v0.13+ 之後支援 Push notifications 然而在這篇文章撰寫時仍然未實做完所有功能。
現階段只支援靜態的推播通知,另外關於錯誤處理的功能也還在開發中Error handling

繼續閱讀

認識 ES6 Decorator

在這篇文章中我們將要探討如何使用 ES7 的新功能.

ES6 新增了一個簡單更具可讀性的語法讓我們可以建立類別(class). 搭配 ES6 匯入匯出模組的語法讓我們的程式更加清楚易懂.

而 Decorators 讓我們可以在設計時期透過註記的方式修改類別與屬性.
在 ES5 物件實字(Object Literal)支援可以使用任意的表達式(Expression)
而 ES6 類別單純只支援使用函式表達式或稱作函式常量(Function Literal)
現在 Decorator 讓 JS 具備了可維護性與可讀性的宣告式語法

繼續閱讀

第一次用 jspm 就上手

何謂 jspm ?

jspm (javascript package manager) 號稱是完全支援(無摩擦)瀏覽器載入的套件管理工具

繼續閱讀

Webpack 筆記

動機

今時今日所謂的網站正進化成網路應用程式,它不再只是單純的顯示圖片文字資訊,而包含著更多互動與操作行為,同時也意味著一個網站:

  • 具有更多的 Javascript
  • 可以在現代的瀏覽器上做更多事
  • 較少全頁重新載入的行為 ➞ 甚至更多程式碼在單一頁面
繼續閱讀