tags:JavaScript 有待補內容 JS102 module npm Unit Tests ES6

JS102 筆記

本章重點

  • Modules
  • npm/yarn
  • Tests(Unit test)
  • ES6

Require & Export

借別人的東西來用:require

概念:

  • 什麼是 module?
    • 把內容依用途分成一個個小模組

實作:

  • 要怎麼導入模組?
    • 在 .js 檔案中用 ·var 變數名 = require('模組名')
    • 如果是自己寫的,'模組名' 會長得像'./myModule.js'
      • 有些東西可以省略,像是 .js

把東西借給別人:export

概念:

  • 怎麼寫一個 module,讓別人和自己可以用?
    • 見實作。

實作:

  • 第一種方法:存到一個變數裡,再 export 出去
    • 為 module 建立一個 .js 檔案
    • 把 module 用 module.exports = function 名 exports 出去
    • 也可以用一個 object 輸出一組 module:
let obj = { dobule: dobule //已有的function,下同 triple: function(n){ return n * 3; } addOne:function(n){ return n + 1; } } module.exports = obj
  • 第二種方法:直接把 functionName export 出去
exports.double = dobule exports.triple = function(n) { return n * 3 }

其他說明:

  • 一樣建議 module 名稱盡量有語意

[示範]有了 module 後的優勢

影片的 12:30 處

  • 有了 module 有什麼好處?
    • 易管理,需要修改時可以改一個地方就好
    • 可重複使用 module

Node Package Manager, NPM

概念:

  • NPM 是什麼?
    • a package manager for JavaScript
    • 自己寫和 Node.js 提供之外的 module 來源(來自網路)

實作:

  • NPM 在下載 Node.js 時通常都已經裝好了
    • 怎麼確認?
      • 在終端機用 npm -v 查看版本號確認是否有下載成功

其他補充:

  • package/ module/ library 這三個的意思是差不多的

npm install:以 left-pad 為例

概念1:

  • 如何把 npm 上的 module 裝到我們的資料夾底下?
    • 見實作
  • npm 把 module 抓下來時到底做了麼?
    1. 開一個叫做 node_modules 的資料夾
    2. 然後把 install 的 package 存進去

實作1:

  • 在終端機用npm install npm名 安裝 npm
  • 用的時候用require導入
var leftPad = require('left-pad');

概念2:

  • 下載很多 npm 的資料夾很大,我們需要每次都commit 上去嗎?
    • 不用, npm 的檔案基本上別人也都下載得到,我們只要讓別人知道用了哪些 npm 他們就可以自己去下載了。
  • 怎麼建立?
    • 見實作2。

實作2:

  • 如何裝 npm 前置

    • npm init 建立一個叫做 package.json 的資料夾
      • 裡面的"dependencies" 物件裡面就我們裝的東西的名稱和版本號
  • 怎麼下載 npm

    • 開發時使用別人的 npm
      • npm install npm名 --save //詳見下面 package.json 及下載別人的程式
  • 怎麼使用 npm

var leftPad = require('left-pad');
  • 在 commit 時,大家都怎麼做?

    • 通常不會把 npm commit 上去
    • 要記得把 npm 所在 folder 的檔名加到一個命名為 .gitignore的文字檔裡面再 commit
  • package.json 是什麼?

    • 寫著關於這個專案的相關資訊的檔案
    • 在下載到有 dependencies (就是有用到其他公開 module)的檔案時, 其他人會參考這裡的資訊去下載檔案。
    • 在根目錄中使用npm init會自動生成
  • 如何把我們用的 library 寫入 json?

    • 在 install 別人的 module 時最後面接 --save
    • (註)npm 5 以後,--save 已經變成預設的選項了,因此 npm install 不加 --save 也一樣會把資訊寫到 package.json 裡面
  • 如何把別人 json裡有的 npm 下載下來?

    • $ npm install進行
  • 忘記 $ npm install會怎樣

    • 會收到 can not find module "module name" 警告
  • 自己有 module 要用 yarn 或 npm 管理時:

    • yarn : 用$ yarn init 進行
    • npm:用$ npm init 進行

npm scripts

概念

  • package.json 的 "script" 區塊是什麼?
    • script 可以寫好一些指令
    • 可以在終端機下指令來執行這些 script 的腳本

實作

  • 怎麼在 "scripts" 裡建立指令
    • 在 package.json 裡的 "scripts" 裡加入腳本
{ ...
"scripts":
{
"hello": "echo Hello, world",
},
...
}
  • 怎麼用 npm 執行指令
    • 在終端機上用 npm run 腳本指令 執行
    • 例:
      $ npm run hello

yarn :npm 以外的選擇

介紹

  • yarn 是什麼?
    • 一個和 npm 有著非常相似功用的 manage 工具
  • yarn 的特色?
    • 是 facebook 開發的一個開放原始碼的東西
    • 比 npm 快
    • 會自動在 module 被下載時加入 json 的 dependencies list 裡

實作

指令 內容
$ yarn add "專案名稱" 等同 npm install 但會自己加入 dependencies
$ yarn -v 查看版本號
$ yarn 根據 json 下載 dependencies
$ yarn run <scriptName> 等同 npm run <scriptName>

Unit test

為什麼要寫測試?

概念

  • 初學者通常怎樣測試 code?
    • 用 console.log()
    • 想一些 edge case(邊界條件)讓程式跑跑看
    • 試著讓測試結果一目了然
function repeat(str, times) { let result = ''; for(let i = 0; i < times; i += 1) { result += str; } return result; } console.log(repeat('a',5) === 'aaaaa') console.log(repeat('abc',1) === 'abc')
  • 缺點
    • 很難規模化
    • 不好執行

利用 Jest 來寫你的第一個測試!

概念

  • 什麼是 Jest?
    • 一套現成的 framwork
    • 可以用來幫助進行測試

技術

  • 怎麼下載 Jest?

  • 怎麼寫測試?

    • 從原本的 .js 檔裡用module.exports = functionName 把 function exports 出來
    • .test.js 的檔案裡用 require 把檔案引用進來
    • 然後照著官網上的寫法針對每一個 unit 寫測試
const stars = require('./hw1');

describe('測試印星星', () => {
  test('應該要有一顆星', () => {
    expect(stars(1)).toEqual(["*"]);
  });
  test('應該要有一到三顆星', () => {
    expect(stars(3)).toEqual(["*", "**", "***"]);
  });
  test('應該要有一到六顆星', () => {
    expect(stars(6)).toEqual(["*", "**", "***", "****", "*****", "******"]);
  });
});
  • 怎麼樣才可以進行測試?
    • 要先有腳本
    • 在 package.json 的 "script" 裡面寫好腳本
  ...
  "scripts":
  {
  "hello": "echo Hello, world",
  "test":"jest",
  ...
  },
  • 或者如果只想測試單一檔案:
  ...
  "scripts":
  {
  "hello": "echo Hello, world",
  "test":"jest hw1.test.js",
  ...
  },
  • 腳本寫好之後,怎麼執行?
    • 第一種辦法:用 $ npm run test
    • 第二種辦法:用 $ yarn run test
    • 第三種辦法(新版本的 npm 的):npx jest hw1.test.js

先寫測試再寫程式: Test-driven development,TDD

概念:

  • 先寫測試再寫 function 的一種開發流程
  • 每改完一次就跑測試,看錯的結果是什麼,再回去改。
  • test case 要盡可能詳細,要盡可能把所有的邊界條件都放進來

配備升級:ES6

概念:

  • 什麼是 ECMAScript?

    • 一個標準、規範
    • Javascript 照著這個規則走
  • const 是什麼?

    • constant 常數
    • 常數不能重新賦值
  • let 和 var 的差別

    • scoped (作用域)的範圍不同
    • let 是以 block 為作用域範圍,var 是以 function 為限

再也不需要字串拼接:Template Literals

概念:

  • 什麼是字串拼接?
    • 把 string 用拼接的方式接起來,就叫做字串拼接
  • 有什麼問題?
    • 問題一:要印多行字串時,要在字串間加入\n才會印多行
    • 問題二:如果拼接的字串太多,很容易出現單雙引號混用等語法問題
  • Template Literals 怎麼解決這些問題?
    • 見實作

實作:

  • 如何用 Template Literals 解決多行字串問題?
    • `` 符號
let str = ` Hello, world. `
  • 如何解決多字拼接問題?
    • 用類似內嵌的方式把變數鑲嵌進來
function sayHi(name) { console.log(`Hello my frind ${name}, now is ${new Date()}`); } sayHi('nick');
  • ${}裡面是可以放程式碼的
  • 例如 ${name.toUpperCase}

聽起來很酷的 Destructuring:解構

  • 有點複雜,好像是把關鍵字(或者是項)拿出來,就可以直接對應到 object 或 array 中的值
  • MDN使用說明
  • 例子:
const obj = { father :'papa', mother :'mama' } let { father } = obj console.log(father); // 'papa'
  • 另外一種用法:在 function 裡面放大括號,直接輸入物件內的變數
function test({a,b}) { console.log(a); } test({ a:1, b:2 }) // 1

Spread Operator

概念:

  • Spread Operator 展開運算子
  • syntax:...
  • 可以展開 object, 包含 array

實作:

let arr = [1, 2, 3]; let arr2 = [4,5,6, ...arr]; console.log(arr2); // [ 4, 5, 6, 1, 2, 3 ]

可以在 object 中展開別人形成新的 obj

let obj = { a:'1', b:'2' } let result = { ...obj, c:3 } console.log(result); // { a: 1, b: 2, c: 3 }

也可以展開物件

let arr = [1, 2, 3]; let result = { ...arr, c:3 } // { '0': 1, '1': 2, '2': 3, c: 3 }

但是如果有以數字命名的物件性時,物件內的東西會指向最後給他的東西:

let arr = [1, 2, 3]; let obj = { 0:'o', 1:'p' } let result = { ...arr, ...obj, c:3 } console.log(result); // { '0': 'o', '1': 'p', '2': 3, c: 3 }
  • 也可以用來複製一份別的 object 的內容:
let arr = [1, 2, 3] let arrCopy = [...arr] console.log(arrCopy) console.log(arr1 === arrCopy) // [1, 2, 3] // false
  • 如果用 obj = obj2 的方式,兩者會指向同一個記憶體位置,此時改變 obj 的值時就會連帶改變 obj2 的值
  • 因此如果要複製的是 obj2 的值時 ...運算子會很好用。

「反向」的展開:Rest Parameters

概念:(待補)
syntax:...rest


加上預設值:Default Parameters

概念

  • 為 function 的 Parameters 設定預設值

實作

function repeat (str = 'hello', times = 2) { console.log(times); return str.repeat(times); } console.log(repeat()); // 2 // hellohello

Function 的更新:箭頭函式 Arrow Function

概念

  • 一個宣告 function 的新方法

實作

原本的寫法:

let arr =[1, 2, 3, 4, 5]; console.log( arr .filter(function(value) { return value > 1 }) .map(function(value){ return value * 2 }) )

有 arrow function 的寫法:

console.log( arr .filter(value => { //把 function 刪掉,然後只有一個參數時,() 也可以省略 return value > 1 }) .map(value => { return value * 2 }) )

更省略的寫法:

console.log( arr .filter(value => value > 1) // 整個 () 都不要,直接回傳 .map(value => value * 2) )

Import 與 Export

概念

  • 在 ES6 上面的新的 function import/export 語法

範例
舊寫法:

// export function add(a,b){ return a + b } module.exports = add // import let add = require('./utils') console.log(3,5)

新寫法:

// export export function add(a,b){ // 這裡前面加了 export return a + b; } export const PI = 3.14; // 這裡前面加了 export // import import {add, PI} from './utils' // 新語法 console.log(3,5)
  • 現在的 node 還沒辦法跑 ES6 的 import/export 代碼
  • 可以用 bable-node指令來跑

其他變形:

// export function add(a,b){ return a + b; } let const PI = 3.14; export{ add, PI }

如果想要以其他名稱 export 出去

export{ add as addFunction, PI } // 記得 import 時也要用這個新名稱才找得到是誰

一次全部 import

import * as utils from './utils' // * 就是指所有東西 console.log(utils.addFunction(3,5), utils.PI);

總結:
Export 有幾種方式:

export function add(){},使用 import {add} 引入
export { add },與上面那種一樣
export default function add(),使用 import add 引入,不需要加大括號
如果想要用其他名字,可以用 as 取別名,例如說 export { add as addFunction }

可以用 import * as utils from 'utils' 把全部都 import 進來


Babel 簡介與基本使用方法

概念

  • 什麼是 babel?
    • a JavaScript compiler
    • Bable 官網
    • 為支援度不足的環境,對 code 進行編譯,讓原本不支援的環境也可以跑
      • ES6/7/8 => Babel => ES5(或其他更舊的)
    • 是一個前端開發的工具
    • 前端開發的變化速度比瀏覽器還要快,所以試圖讓彼此相容的工具也很多
      實作:
      參考bable影片

更多 ES6

Select a repo