雖然現在寫代碼不像以前,現在都有 eslint、prettier、babel(寫新版語法) 這些來保證代碼格式,然而,技術手段再高端都不能解決代碼可讀性(代碼能否被未來的自己和同事看懂)的問題,因爲這個問題只有人自己才能解決。要想寫出不讓你同事或者你的交接人吐槽的代碼,首先要有良好的代碼風格,下列編碼陋習你有木有?有的話改進改掉吧!!!
掌握一些JavaScript小技巧有利於你提高代碼質量哦!下面我們一起來學習吧!!
1.濫用變量
定義好了之後再也沒用過
改進:
數據只使用一次或不使用就無需裝到變量中,沒用的就刪除掉,不然過三個月自己都不敢刪,怕是不是那用到了
2.自我感覺良好的縮寫
let fName = 'jack'; // 看起來命名挺規範,縮寫,駝峯法都用上,ESlint 各種檢測規範的工具都通過,
//But,fName 是啥?這時候,你是不是想說 What are you 弄啥呢?
let lName = 'tom'; // 這個問題和上面的一樣
改進:
let firstName = 'jack'; // 怎麼樣,是不是一目瞭然。少被噴了一次
let lastName = 'tom';//無需對每個變量都寫註釋,從名字上就看懂
3.無說明的參數
if (value.length < 8) { // 爲什麼要小於 8,8 表示啥?長度,還是位移,還是高度?Oh,my God!!
....
}
改進:
const MAX_INPUT_LENGTH = 8;//添加變量
if (value.length < MAX_INPUT_LENGTH) { // 一目瞭然,不能超過最大輸入長度
....
}
4.命名過於囉嗦
let nameString;
let theUsers;
改進:
簡潔明瞭就行
let name;
let users;
5.使用太多的全局變量
name.js
window.name = 'tom';
hello.js
window.name = 'bobu';
time.js
window.name = 'cater'; // 三個文件的先後加載順序不同,都會使得 window.name 的值不同,
//同時,你對 window.name 的修改了都有可能不生效,因爲你不知道你修改過之後別人是不是又在別的說明文件中對其的值重置了。
//所以隨着文件的增多,會導致一團亂麻。
改進:
少用或使用替代方案:你可以選擇只用局部變量。通過 (){}的方法。
如果你確實用很多的全局變量需要共享,你可以使用 vuex,redux 或者你自己參考 flux 模式寫一個也行。
6.從命名無法知道函數返回值類型
function showDatas() {....} // 現在問,你知道這個返回的是一個數組,還是一個對象,還是 true or false
改進:
對於返回 true or false 的函數,最好以 should/is/can/has 開頭
function shouldShowData() {...}
function isEmpty() {...}
function canSubmit() {...}
function hasLicense() {...}
7.功能函數的輸出變化無常
function plusAbc(a, b, c) { // 這個函數的輸出將變化無常,因爲 api 返回的值一旦改變,同樣輸入函數的 a,b,c 的值,但函數返回的結果卻不一定相同。
var c = fetch('../api');
return a+b+c;
}
改進:
功能函數使用純函數,輸入一致,輸出結果永遠唯一
function plusAbc(a, b, c) { // 同樣輸入函數的 a,b,c 的值,但函數返回的結果永遠相同。
return a+b+c;
}
8.傳參無說明
getLisence(src, true, false); // true 和 false 啥意思,一目不了然
改進:
傳參有說明
getLisence({
image: src,
includePageBackground: true, // 一目瞭然,知道這些 true 和 false 是啥意思
compress: false,
})
9.無法辨別函數意圖
改進:
動詞開頭,函數意圖就很明顯
function sendEmailr(user) {
....
}
10.函數中過多的採用 if else
function getGrades(num){
let result='';//返回結果
if(num < 60) {
result = "不及格";
}else if(num < 75) {
result = "一般";
} else if(num < 90){
result = "良好";
}else{
result = "優秀";
}
return result;
}
console.log(getGrades(60))
改進:
1.可以使用 switch 替代或用數組替代
function showGrace(grades,results,curr) {
for(let i in grades){
if(curr<grades[i]){
return results[i]
}
}
}
let grades=[60,75,90,101],
results=['不及格','一般','良好','優秀'];
showGrace(grades,results,60)
2.短路求值(Short-Circuit Evaluation):三目運算符是一個很方便快捷的書寫一些簡單的邏輯語句的方式,
x > 100 ? ‘Above 100’ : ‘Below 100’;
x > 100 ? (x > 200 ? ‘Above 200’ : ‘Between 100-200’) : ‘Below 100’;
11.if判斷條件太多
if(fruit==='apple' || fruit==='apple' || fruit==='strawberry' || fruit==='cherry' || fruit==='cranberries'){
console.log('red');
}else{
console.log('blue');
}
改進:
利用數組列舉條件,
array.indexOf 此方法判斷數組中是否存在某個值,如果存在返回數組元素的下標,否則返回-1;
array.find(callback[, thisArg]) 返回數組中滿足條件的第一個元素的值,如果沒有,返回undefined;
array.findIndex(callback[, thisArg]) 返回數組中滿足條件的第一個元素的索引(下標), 如果沒有找到,返回-1
array.includes(searchElement[, fromIndex]) 此方法判斷數組中是否存在某個值,如果存在返回 true,否則返回false。
function test(fruit) {
const redFruits = ['apple', 'strawberry', 'cherry', 'cranberries'];
if (redFruits.includes(fruit)) {
console.log('red');
}else{
console.log('blue');
}
}
12.有效性數據返回判斷
if (this.state.data) {
return this.state.data;
} else {
return 'Fetching Data';
}
但是我們可以通過上面的方式來簡寫這個邏輯處理。
return (this.state.data || 'Fetching Data');
13.儘量使用 ES6
1.儘量使用箭頭函數
2.不採用傳統 + 號,採用模板字符
// var message = 'Hello ' + name + ', it\'s ' + time + ' now'
改進:var message = `Hello ${name}, it's ${time} now`
3.使用解構賦值
傳統賦值:
var data = { name: 'dys', age: 1 };
var name = data.name;
var age = data.age;
var fullName = ['jackie', 'willen'];
var firstName = fullName[0];
var lastName = fullName[1];
改進:
解構賦值:
const data = {name:'dys', age:1};
const {name, age} = data; // 怎麼樣,是不是簡單明瞭
var fullName = ['jackie', 'willen'];
const [firstName, lastName] = fullName;
4.儘量使用類 class
採用傳統的函數原型鏈實現繼承
典型的 ES5 的類 (function) 在繼承、構造和方法定義方面可讀性較差,當需要繼承時,優先選用 class。代碼太多,就省略了。
改進:
採用 ES6 類實現繼承
class Animal {
constructor(age) {
this.age = age
}
move() {
/* ... */
}
}
class Mammal extends Animal {
constructor(age, furColor) {
super(age)
this.furColor = furColor
}
liveBirth() {
/* ... */
}
}
class Human extends Mammal {
constructor(age, furColor, languageSpoken) {
super(age, furColor)
this.languageSpoken = languageSpoken
}
speak() {
/* ... */
}
}
5.過濾唯一值
Set類型是在ES6中新增的,它類似於數組,但是成員的值都是唯一的,沒有重複的值。結合擴展運算符(…)我們可以創建一個新的數組,達到過濾原數組重複值的功能。
const array = [1, 2, 3, 3, 5, 5, 1];
const uniqueArray = […new Set(array)];
console.log(uniqueArray); // [1, 2, 3, 5]
在ES6之前,我們如果想要實現這個功能的話,需要的處理代碼要多很多。這個技巧的適用範圍是數組中的數值的類型爲:undefined, null, boolean, string, number。當包涵object, function, array時,則不適用。
附:小技巧
1、轉換Boolean型
常規的boolean型值只有 true 和 false,但是在JavaScript中我們可以將其他的值認爲是 ‘truthy’ 或者 ‘falsy’的。
除了0, “”, null, undefined, NaN 和 false,其他的我們都可以認爲是‘truthy’的。
我們可以通過負運算符!將一系列的變量轉換成“boolean”型。
const isTrue = !0;
const isFalse = !1;
const alsoFalse = !!0;
console.log(isTrue); // Result: true
console.log(typeof true); // Result: "boolean"
2、轉換String型
我們可以通過+連接運算符將一個number類型的變量轉換成string類型。
const val = 1 + "";
console.log(val); // Result: "1"
console.log(typeof val); // Result: "string"
3、轉換Number類型
和上面對應的,我們可以通過加法運算符+將一個string類型的變量轉回爲number 類型的。
let int = "15";
int = +int;
console.log(int); // Result: 15
console.log(typeof int); Result: "number"
在某些上下文中,+將被解釋爲連接操作符,而不是加法操作符。當這種情況發生時(您希望返回一個整數,而不是浮點數),您可以使用兩個波浪號: ~~ 。
(需要注意爲英文格式)
一個波浪號~,被稱爲“按位不運算符”,等價於 - n - 1。所以~15 = -16.
使用兩個~~可以有效的否定運算。這是因爲 - (- n - 1) - 1 = n + 1 - 1 = n。也就是說 ~-16 = 15
const int = ~~"15"
console.log(int); // Result: 15
console.log(typeof int); Result: "number"
4、快速求冪
從ES7開始,我們可以使用冪運算符 ** 作爲求冪的簡寫,相對之前的Math.pow(2, 3) 更加快捷。這是一個很簡單實用的點,但是大部分的教程並不會專門介紹它。
console.log(2 ** 3); // Result: 8
這不應該與 ^ 符號混淆,^ 符號通常用於表示指數,但在JavaScript中是位XOR操作符。
在ES7之前,冪的簡寫主要依靠的是位左移位操作符 <<,幾種寫法的區別。
// 下面幾種寫法是等價的
Math.pow(2, n);
2 << (n - 1);
2**n;
其中需要注意的是 2 << 3 = 16 等價於 2 ** 4 = 16
5、快速Float轉Integer
我們平時可以使用Math.floor(), Math.ceil()和Math.round()將float類型轉換成integer類型。
但是還有一種更快的方法可以使用|(位或運算符)將浮點數截斷爲整數。
console.log(23.9 | 0); // Result: 23
console.log(-23.9 | 0); // Result: -23
| 的行爲取決於處理的是正數還是負數,所以最好只在確定的情況下使用這個快捷方式。
如果n是正數的,則 n | 0 有效地向下舍入。如果n是負數的,它則有效地向上取整。更準確地說,該操作結果是直接刪除小數點後的內容,將浮點數截斷爲整數,和上面提到的其他幾個方法是有所區別的。
您還可以使用 ~~ 來獲得相同的舍入效果,如上所述,實際上任何位操作符都會強制浮點數爲整數。這些特殊操作之所以有效,是因爲一旦強制爲整數,值就保持不變。
使用場景:
位或運算符可以用於從整數的末尾刪除任意數量的數字。這意味着我們不必使用這樣的代碼在類型之間進行轉換。
let str = "1553";
Number(str.substring(0, str.length - 1));
而是可以使用下面的方式來實現我們的功能
console.log(1553 / 10 | 0) // Result: 155
console.log(1553 / 100 | 0) // Result: 15
console.log(1553 / 1000 | 0) // Result: 1
6、類中自動綁定
我們可以在類中通過使用ES6增加的箭頭函數的方式來實現隱形綁定作用域。而按照之前的處理,我們需要顯式的去爲我們寫的方法進行綁定,類似於 this.myMethod = this.myMethod.bind(this)這樣。當我們的類中有很多方法時,會增加大量的綁定的代碼的書寫。現在我們就可以通過箭頭函數的方式來簡化這個過程。
import React, { Component } from React;
export default class App extends Compononent {
constructor(props) {
super(props);
this.state = {};
}
myMethod = () => {
// 隱式綁定
}
render() {
return (
<>
<div>
{this.myMethod()}
</div>
</>
)
}
};
7、截取數組
如果您想從數組的末尾刪除值,有比使用splice()更快的替代方法。
例如,如果你知道原始數組的長度,就可以通過重新定義它的length屬性來實現截取。
let array = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
array.length = 4;
console.log(array); // Result: [0, 1, 2, 3]
這是一個特別簡潔的解決方案。但是,slice()方法的運行時更快。如果速度是你的主要目標,考慮使用下面的方式。
let array = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
array = array.slice(0, 4);
console.log(array); // Result: [0, 1, 2, 3]
8、獲取數組中的最後的元素
數組方法slice()可以接受負整數,如果提供它,它將從數組的末尾開始截取數值,而不是開頭。
let array = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
console.log(array.slice(-1)); // Result: [9]
console.log(array.slice(-2)); // Result: [8, 9]
console.log(array.slice(-3)); // Result: [7, 8, 9]
9、格式化JSON代碼
我們可能在處理一些JSON相關的處理時很多時候都會使用到JSON.stringify,但是你是否意識到它可以幫助縮進JSON呢?
stringify()方法接受兩個可選參數:一個replacer函數和一個space值,replacer函數可以用來過濾顯示的JSON。
space值接受一個整數,表示需要的空格數或一個字符串(如’\t’來插入製表符),它可以使讀取獲取的JSON數據變得容易得多。
console.log(JSON.stringify({ alpha: 'A', beta: 'B' }, null, '\t'));
// Result:
// '{
// "alpha": A,
// "beta": B
// }'