2017年1月15日

[筆記] JavaScript ES6 中的陣列解構賦值(array destructuring)

在 ES6 中過去的陣列和物件可以透過解構(destructuring)的方式來賦值。這篇文章中,我們會先說明如何透過陣列的方式來賦值。

陣列解構賦值的方法(array destructuring)

過去陣列內的元素在賦值的時候,只能透過直接給值的方式,像是下面這樣:
let numbers = [1, 2, 3];
let a = numbers[0];
let b = numbers[1];
let c = numbers[2];
console.log(a,b,c);   // 1, 2, 3

一般用法

然而在 ES6 中可以直接透過解構的方式賦值,像是下面這樣子:
let [a, b, c] = [1, 2, 3];
console.log(a, b, c); // 1, 2, 3
如此變數 a = 1, b = 2, c = 3,這是最基本的陣列解構賦值方式。

當輸入的變數多於所給的值

當變數的數量多於賦予的值時,多出來的那個變數會被賦予 undefined 的值(d = undefined):
// 當變數多於所給的值
let [a, b, c, d] = [1, 2, 3];
console.log(a, b, c, d); // 1, 2, 3, undefined

當輸入的變數少於所給的值

當輸入的變數少於所給的值的時候,只有被指定到的變數會有值,少掉的變數可以直接空過去,這時候 g = 1, i = 3:
// 當變數少於給的值
let [g, , i] = [1,2,3];
console.log(g, i);  // 1, 3

在陣列解構中賦予預設值

我們也可以在陣列解構中賦予預設值,像是下面這樣:
let [a, b, c = 4, d = 'Hello'] = [1, 2, 3];
console.log(a, b, c, d); // 1, 2, 3, "Hello"
如此就可以將變數 c 賦予 4,d 賦予 Hello 的預設值,輸出的結果 c 因為後面有給值,所以依然是 3 ,而 d 在後面沒有給值,就直接帶入了預設值,得到 “Hello"。

防雷須知

如果你使用的是 standardJS 當作你的 code style,那麼你應該很習慣在結尾不加分號,但是在使用陣列的結構賦值時,這麼做 有可能會噴錯誤。
例如這樣:
let x = 0
let y = 0
console.log(x, y)
[x, y] = [1, 2]
console.log(x, y)
這時候會得到 "TypeError: Cannot set property '0' of undefined 的錯誤。首先簡單說明一下之所以可以不用在結尾加分號是因為在 多數情況下,
在語句或一段代碼敘述後,加了Enter鍵(\n)後,JS剖析器會在執行期間自動幫你插入分號 @ eddyChang
上面提到是多數情況,但是在 某些情況下 JS 引擎是不會幫你加上分號的,其中像是這裡的開頭以 [ 開頭的語句。因此在這裡,請記得在 [ 的前面加上分號,寫起來會像是這樣 ;[x, y] = [1, 2]
更多關於分號的使用請參考 JavaScript裡的語句用分號結尾是個選項嗎 @ eddyChang

資料來源

[筆記] JavaScript ES6 中的函數預設值(default value)


在過去如過要在函式中建立預設值常常要利用到 JS 中強制轉換型別(coercion)的這種特性,但在 ES6 中則可以用相當簡易的方式就可以設定函式的預設值(default value),寫起來更簡潔方便,讓我們來看一下可以怎麼樣使用。

函式預設值的使用


函式預設值的使用非常簡單,只需要在函式中給予參數的地方用等號賦值就可以了,方式如下:

function add(x = 3, y = 5){
  console.log(x+y);
}

add();  // 8

也就是說,只要在 add 這個函式的參數位置寫 add(x =3, y=5) 就可以直接帶入預設值,因此雖然我在執行 add( ) 的時候沒有帶入任何的參數值,但它不會報錯,而是回傳 8 。

使用預設值的基本觀念


丟入的參數值會由前往後代入

假設我只給予後面的 y 預設值,如下:

function add(x, y = 5){
  console.log(x+y);
}

add(2);   // 7
add(2,8); // 10


這時候我可以只輸入一個參數是沒有問題的,這個值會先被丟到 x 這個參數。然而,如果我只給予前面的 x 預設值,如下:

function add(x = 3, y){
  console.log(x+y);
}

add(2);   // NaN
add(2,8); // 10


這時候當我輸入 add(2) 來執行這個函式時,因為 2 會先被帶入 x ,所以 x = 2;而 y 沒有被賦值,因此 y = undefined,這也使得最後回傳的結果會是 NaN。


2017年1月14日

[筆記] JavaScript ES6 中的箭頭函數(arrow function)及對 this 的影響


在這篇文章中要來說明一下在 ES6 中相當常見的箭頭函數(arrow function),讓我們來看一下可以怎麼樣使用。

什麼是箭頭函數(arrow function)


首先,我們來看一下過去我們撰寫函數的方法:



在 ES6 中,我們可以把它改成箭頭函數的寫法,它會變成下面這樣:


沒有參數的時候要記得加上空括號

要特別留意的地方是,在箭頭函數中如果沒有帶入參數時,一樣要加上空括號。



如果只是要回傳某個值,可以省略 return

如果我們的函式本身只是要回傳某個值的話,可以把 return 這個字省略掉:


箭頭函數帶入參數值


兩個以上的參數,需要使用括號

當我們的函式擁有兩個以上的參數時,我們一樣要使用括號來帶入參數,寫法像是下面這樣子:


當函數只有一個參數時,不需要使用括號

從上面的例子我們可以知道,當函數沒有參數或有兩個以上的參數時,我們都要加上括號( ),但是當函數只有一個參數時,可以省略括號不寫,因此,當我們的函數只有一個參數時,我們的函數長得像這樣:



箭頭函數當中的 this 是定義時的對象,而不是使用時的對象


在使用箭頭函數時,有一點要注意的是,在箭頭函數中,this 指稱的對象在所定義時就固定了,而不會隨著使用時的脈絡而改變。

讓我們來看一下這個例子:

在這個範例中,不論我們使用的是原本 function 的寫法或 ES6中的箭頭函式,都會回傳得到最外層的 window 物件(如果不清楚 this 的話可以先參考 [筆記] 談談JavaScript中的"this"和它的bug),這樣看起來似乎兩者沒有太大的差別。



然而,換個例子的情況就不一樣,讓我們來看看下面兩個不同的例子:

例子一(參考自 阮一峰 - ECMAScript 6 入門

我們分別用原本的寫法和箭頭函示的寫法建立了兩個 function:

// 原本的 function
let fn = function(){
  console.log(this.constructor.name);  // Object(data)
  setTimeout(function(){
    console.log(this.constructor.name) // Window
  },100);
}

// 箭頭函式 Arrow function
let fn_arr = function(){
  console.log(this.constructor.name);  // Object(data)
  setTimeout(() => {
    console.log(this.constructor.name) // Object(data)
  },100);
}

let id = 21;
let data = {
  id: 21
}

fn.call(data);     
fn_arr.call(data); 


setTimeout:裡面都分別帶入 setTimeout 的函式,我們知道 setTimeout 執行的時間會在整個 JS execution context 都被執行完後才會執行(如果對這概念不清楚的話可參考:[筆記] 談談JavaScript中的asynchronous和event queue),因此函式建立的時間和實際執行的時間是不同的,因此這也創造了兩個不同時間點的 this 所指稱的對象。

call:另一個要了解的是 call 的用法,在 call 當中,我們會帶入後面所指定的物件當作所指稱的 this 對象(對這個概念不清楚的話可參考:[筆記] 了解function borrowing和function currying ─ bind(), call(), apply() 的應用)。

this.constructor.name:這樣子的寫法只是避免在回傳出物件的時候把整個物件內容給傳出來,而是指示傳出該物件的名稱(參考自:stackoverflow)。

綜合上述,我們可以知道,因為有用 call(data) 的緣故,因此不論是使用傳統函式寫法(fn)或箭頭函式(fn_arr)時,在一開始函式裡面的 this 都指稱的是 data 這個物件。

然而不同的地方會在執行 setTimeout 中的函式,在使用傳統函式的寫法時,使用 fn.call(data) 時,因為它執行的時間點是在整個 JS execution context 執行完才執行,而當時的環境會變成是 global environment,因此使用傳統函式時,這個 this 指稱的對象會轉變成 window object 。但是,如果是使用新的箭頭函式(arrow function),這個 this 所指稱的對象則不會改變,依然是 data 這個 object

範例:https://jsbin.com/wodegu/edit?js,console

例子二(參考自 Accelerated ES6 JavaScript Training

第二個例子是使用 addEventListener 來達到示範,首先我們在 HTML 中建立一個 button element,然後利用 JS 來抓取這個 button,接著 JS 部分則如下所示:

var button = document.querySelector('button');
var fn_arr = () => {
  // 建立 function 時 this 指 Window
  console.log(this.constructor.name)  // 執行function時 this 指 Window
};
var fn = function(){
  // 建立 function 時 this 指 Window
  console.log(this.constructor.name)  // 執行function時 this 指 HTMLButtonElement

button.addEventListener('click', fn_arr);


和例子一中的 setTimeout 類似,我們使用的 addEventListener ,也會在整個 execution context 執行結束後,在網頁觸發事件時才執行。

因此不論在傳統的函式寫法(fn)或箭頭函式(fn_arr)的寫法,一開始建立 function 的時候 this 所指稱的都是  window 這個物件,然而,如果是使用傳統的寫法,在觸發這個事件時所指稱的對象會從原本的 window 變成 HTMLButtonElement;若使用的是箭頭函式,則會固定所指稱的對象,因此 this 依然指稱的是 window 這個物件。

範例:https://jsbin.com/kotetu/edit?js,output

2017年1月4日

[筆記] JavaScript ES6 中使用 const 宣告常數


在 ES6 中可以透過 const 來宣告變數,究竟 const 有什麼特別的地方呢?

首先 const 的意思是 constant ,也就是常數的意思,當我們宣告它之後,它是不能在被改變的,但實際上在使用時仍然有一些需要注意的地方,讓我們先來看一下下面的例子:

當我們使用 const 來宣告變數時,就像和使用 let 一樣,都可以得到 27 的結果:


可是當我對這個 const 重新指派值時,就會出現錯誤訊息:


也就是說 age 它在這裡其實是被設定成一個常數,而不是一個變數。 透過 const 我們可以宣告常數

因此,為了方便區分哪些是常數那寫是變數,我們可以把常數在宣告的時候用大寫來表示,像是這樣:


使用 const 在宣告陣列或物件時需要留意的地方


這麼看起來 const 似乎很容易理解,但是有幾種狀況必須非常小心,當 const 使用在陣列(array)或物件(object)的時候需要特別留意,讓我們來看一下使用在陣列的情況:

當我們已經使用 const 宣告好一個常數,接著在用 push 去推入一個陣列的值時,並不會有錯誤的情形產生。


之所以不會有錯誤,是因為在 JS 中陣列(array)和物件(object)都是屬於 reference type,因此實際上我們並沒有把這個常數指向(pointer)另一個東西,它仍然指稱到的是同一個記憶體位置。

如果不清楚 by reference 的意思,可以參考:[筆記] 談談JavaScript中by reference和by value的重要觀念

同樣的道理,如果我們使用的是物件(object),一樣不會有錯誤的情形產生:


然而,還有一點需要提醒的是,如果你是使用 object literal 的方式修改物件的內容,那對於 JS 引擎來說,就等於是建立了一個新的物件,也就是它會將這個物件存到另一個記憶體位置,意思就是這個常數的值改變了,如此的話,同樣會出現錯誤的訊息(陣列也是一樣的道理):


const 和 let 一樣都是block-scoped


最後一點是 const 和 let 一樣,所宣告的變數都是僅在代碼區塊內有效(block-scoped),也就是僅在限定的{ }內有效:





2017年1月3日

[筆記] JavaScript ES6 中使用block-scoped 的 let 宣告變數



最近開始在 Udemy 上學習和另一個與 JavaScript 有關的課程ㄧ Accelerated ES6 JavaScript Training,主要的內容是針對 ES6(ECMAScript 6)加以學習,因此接下來會整理這門課程當中的內容還有其他網頁資源作為自己的學習筆記,有想要一同學習的夥伴們也可以持續 follow ,另外,因為我也是在持續學習的過程中,所以如果有任何觀念或語法上的錯誤,也非常希望比較有經驗的大大們可以協助改正。

使用 let 宣告變數


在 ES6 中有一個新的關鍵字 let ,let 的用法和過去使用的 var 非常相似,都可以用來宣告變數:

在這裡我們可以看出,不論是用 var 或用 let 都能得到相同的結果。


然而,var 和 let 最主要的差別在於 let 所宣告的變項只有在代碼塊區域(block scope)內有效,讓我們繼續看下去:

當我們使用 var 來宣告變數時,因為它不會受限於在代碼區塊內,所以一樣可以輸出變數內容。


但是當我們使用的是 let 的時候,一切就不同了,因為 let 所宣告的變數只能做用到代碼塊區域(block scope)中,所以當我們在 { } 外面要呼叫用 let 所定義的 author 這個變數時,就會出現 error:


簡單一句話來說:用 let 所定義的變數只能作用在所屬的 { } 中有效



2016年10月20日

[資源] 適合打 code 時清楚簡潔的字體選擇---Fira Code


認識 PJ 的人應該都知道,PJ 在寫 code 的時候,很重視編輯器撰寫時視覺上舒適的感受,總覺的畫面好看的編輯器打起 code 來就是比較舒服,用起來就是比較開心。

最近在網路上發現了一個免費字體 Fira Code ,一開始使用的時候,還覺得有些字體變得好像有襯線的感覺而不太習慣,但嘗試一下子之後,發現這個字體非常的清晰易讀,對於每天在碼海中的工程師們非常合適,可以來嘗試用用看!

下載網址:https://github.com/tonsky/FiraCode

目前大多數的編輯器(Atom, Brackets, VSCode)都有支援這款編輯器的連字功能(ligatures), sublime text 目前雖然還沒有支援這款編輯器的連字功能,但一樣能夠套用字型到編輯器當中。

Sublime Text 使用方式


下載並安裝

首先,到FiraCode的 Github 頁面下載字體,在下載的檔案中包含 ttf 的字型資料夾檔,打開並根據所屬的作業系統將字型檔安裝在作業系統上。

套用於 sublime

打開 Sublime Text 後進入 Preference --> Settings

這時候一般會同時開啟兩個視窗,左邊的是 Default , 右邊的是 User。


我們要在 User 的設定檔中新增一行 "font_face": "Fira Code",,如下圖中第四行所示:


存檔後,應該就可以順利將字體套用上去了。

如果你也很在意編輯器好不好看,視覺上舒不舒服的朋友們,也可以下載來試試看!

2016年10月10日

[資源] 假圖產生器 Fake Image Placeholder



再製作網頁的過程中,常常會有一些版面的位置可能是已經知道圖片的大小,但是設計師還沒有把圖切好給你,這時候空一個位置在那不僅不方便我們看整體版面的配置,在美觀上也常常給人一種未完成品的感覺。

這時候,你可以用簡單方便的假圖產生器快速生成一個圖,先把圖放在版面上,之後等實際的圖片切好之後,再把完成的圖置換上來就可以了。

假圖產生器網址:http://fakeimg.pl/

使用方式


使用方法非常的簡單,只需要在 http://fakeimg.pl/300x250/ 標住顏色的位置更改為想要的尺寸就可以了。


更改顏色

如果你覺得灰色太過單調,你可以在網址後方多帶一些參數,就可以達到換色的效果,例如: http://fakeimg.pl/440x320/282828/EAE0D0/ ,其中第一個參數是給背景色,第二個參數是給文字顏色(也可以不給),結果如下圖:


更改文字內容

同樣地,如果你想要更改文字內容,也可以透過給予參數的方式來更改,像是 http://fakeimg.pl/440x300/282828/EAE0D0/?text=PJCHENder ,或者如果不想改顏色,只想改文字的話,可以輸入 http://fakeimg.pl/440x300/?text=PJCHENder 也可以。


非常的簡單好用,利用這個簡單的小功能,從此不用在自己製作假圖,相信也將節省很多開發上的時間。

假圖產生器網址:http://fakeimg.pl/

這個功能也有開發 sublime text 的 plugin ,安裝後只要在 sublime 中打"fakeimg" 就會產生對應的連結網址了!