此篇將繼續接續上篇,介紹一些寫 JS 的技巧。
in 運算子可以用來確認一個物件是否有某個屬性。
const person = { name: 'harry' };
console.log('age' in person); // false
console.log('name' in person); // true
用在陣列時可以確認是否該陣列的某索引有無元素。
範例中陣列索引 2 能找到是 Alice,而索引 5 找不到元素,印出 false
const members = ['Jay', 'Mandy', 'Alice', 'Tom'];
console.log(2 in members); // true
console.log(5 in members); // false
type Fish = { swim: () => void };
type Bird = { fly: () => void };
type Human = { swim?: () => void; fly?: () => void };
function move(animal: Fish | Bird | Human) {
if ("swim" in animal) {
// animal: Fish | Human
} else {
// animal: Bird | Human
}
}
這個語法看起來平易近人但也不算常用到,以下來舉幾個例子說明它的作用。
const x = 1;
const y = (x + 1, x + 2, x + 3);
console.log(y); // 4
從範例中看到 Comma operator 就是 (x + 1, x + 2, x + 3)
的部分,用小括號包起來,然後裡面放數個運算式,也可以是一個單純的值,它會從左到右執行,最後回傳最右邊運算的結果,這個範例就是單純的運算 x + 3
,所以 y 被賦予 4 的值。
let x = 1;
const y = (x ++, x += 2, x += 3);
console.log(y); // 7
這個範例它會不斷的累加 x 的值,最後右邊運算完後回傳 7 並賦予給 y。
for (let i = 0, j = 9; i <= 9; i++, j--) {
console.log(`[${i}][${j}]`);
}
實際應用的例子就是 for 迴圈可以加入多個參數去做執行,讀者可以先預測一下會印出什麼樣的結果再實際執行這段程式碼。
產生指定長度的空陣列
const emptyArr = new Array(10);
console.log(emptyArr); // [empty × 10]
console.log(emptyArr.length); // 10
console.log(emptyArr[1]); // undefined
然後可搭配 fill 去為空陣列填入指定的值。
const fillArr = new Array(5).fill(2);
console.log(fillArr); // [2, 2, 2, 2, 2]
用 Array.from 也能達到相同效果。
const fillArr = Array.from({ length: 5 }, () => 2);
console.log(fillArr); // [2, 2, 2, 2, 2]
前面的 fill() 再加上 map() 產生二維陣列。
const matrix = Array(5).fill(0).map(()=>Array(5).fill(0));
console.log(matrix);
// [[0, 0, 0, 0, 0],[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]]
淺複製陣列的四個方式
// 方法1: 利用回傳新陣列的特性
const team2 = players.slice();
// 方法2: 空陣列連接 players,也是出現新陣列
const team3 = [].concat(players);
// 方法3:
const team4 = [...players];
// 方法4: 利用回傳新陣列的特性
const team5 = Array.from(players);
let nums = '1234534236'.split('').map(Number);
console.log(nums); // [1, 2, 3, 4, 5, 3, 4, 2, 3, 6]
const splitMsgs = 'qwertyuiopasdfghjklzxcvbnm'.match(/(.{1,5})/g);
console.log(splitMsgs); // ['qwert', 'yuiop', 'asdfg', 'hjklz', 'xcvbn', 'm']
const members = ['Jay', 'Mandy', 'Alice', 'Tom'];
members.length = 2; // 指定陣列剩兩個元素
console.log(members); // ['Jay', 'Mandy']
之前都沒注意到 map() 可以帶第三個參數(比較少用到),也就是呼叫 map 方法的陣列。
所以以下這題 Codewar 可以這樣解:
function duplicateEncode(word){
return word.toLowerCase().split('').map((char, index, callArr) => {
return callArr.indexOf(char) === callArr.lastIndexOf(char) ? '(' : ')';
}).join('');
}
const randomNums = [1, 4, 7];
randomNums.forEach((num, index, callArr) => {
callArr[index] *= callArr[index];
})
console.log(randomNums); // [1, 16, 49];
Google 搜尋 二維陣列轉一維陣列 js 可以看到不少將二維陣列轉成一維陣列的方法,我這裡也分享一個很簡單的方式,運用 concat + 展開運算子即可,如以下範例:
console.log([].concat(...[[1], [2], [3]])); // [1, 2, 3]
console.log([].concat([[1], [2], [3]])); // [[1], [2], [3]]
個人認為依照功能分類檔案會更好,調整相關功能就不用到處翻其他資料夾查找。
依照檔案類型分類:
.
├── components
│ ├── todos
│ └── user
├── reducers
│ ├── todos
│ └── user
└── tests
├── todos
└── user
依照功能分類:
.
├── todos
│ ├── component
│ ├── reducer
│ └── test
└── user
├── component
├── reducer
└── test
if (missingValue)
比起 if (!hasValue)
更明確if (anonymous)
比起 if (!user)
更明確if (isEmpty(thing))
比起 if (notDefined(thing))
更明確
以下再另外介紹一些工具,可以幫助我們寫出品質更好的程式碼。
ESLint 可以幫你做靜態語法分析,找出一些語法錯誤、統一 coding style、提示哪些套件和變數等已經引入和宣告卻沒有使用到等...。
在存檔時做程式碼的自動格式化,像是縮排空幾格、使用單引號還是雙引號等。
幫 JS 程式碼加上註解的好工具,例如函式的註解就會長這樣:
/**
* 測試用方法
* @param a 基準值
* @param b 比較值
* @param c 當基準值與比較值相等時會跳出此參數的內容值
*/
function test(a, b, c) {
if (a===b) {
alert(c);
}
}
如果想要讓寫出的程式品質更好,減少 bug 以及利於重構,那測試肯定不可少,而且寫測試本身還有當參考文件的作用,著名的測試框架如 Jest。
最後提的一點是心態,想要寫出更好的程式碼優良的心態絕不可少,如果想要變成更加傑出的工程師可以多思考自己的程式碼有沒有可以寫得更好的寫法,然後多看看一些優秀的工程師的寫法和程式碼風格。
這兩篇的介紹就到這邊,未來有發現更多的技巧我會繼續補充在這篇,總覺得寫完內容還不夠豐富啊XD!
明天就是鐵人賽的最後一篇文章,我將會介紹 ES 7~13 的幾個語法來做分享。