六種頗有用的編程技巧,幫助你成爲更好的 JavaScript 程序員

1. 常量提取和Array.includes運用

// bad example

function printAnimals(animal) {
    if (animal === 'dog' || animal === 'cat') {
        console.log(`I have a ${animal}`);
    }
}

console.log(printAnimals('dog')); // I have a dog
複製代碼

上面的代碼看起來不錯,由於咱們只有兩個動物要檢查。可是,咱們不肯定用戶輸入。若是咱們還有其餘動物怎麼辦?若是咱們繼續用更多的OR語句來擴展該語句,則代碼將變得更難維護,而不是那麼幹淨。javascript

解:java

咱們可使用重寫上面的條件 Array.includes數組

// good example

function printAnimals(animal) {
    const animals = ['dog', 'cat', 'hamster', 'turtle']; 
    
    if (animals.includes(animal)) {
        console.log(`I have a ${animal}`);
    }
}

console.log(printAnimals('hamster')); // I have a hamster
複製代碼

2. 儘快return

// bad example

const printAnimalDetails = animal => {
    let result;

    // condition 1: check if animal has a value
    if (animal) {

        // condition 2: check if animal has a type property
        if (animal.type) {

            // condition 3: check if animal has a name property
            if (animal.name) {

                // condition 4: check if animal has a gender property
                if (animal.gender) {
                    result = `${animal.name} is a ${animal.gender} ${animal.type};`;
                } else {
                    result = "No animal gender";
                }
            } else {
                result = "No animal name";
            }
        } else {
            result = "No animal type";
        }
    } else {
        result = "No animal";
    }

    return result;
};

console.log(printAnimalDetails()); // 'No animal'

console.log(printAnimalDetails({ type: "dog", gender: "female" })); // 'No animal name'

console.log(printAnimalDetails({ type: "dog", name: "Lucy" })); // 'No animal gender'

console.log(printAnimalDetails({ type: "dog", name: "Lucy", gender: "female" })); // 'Lucy is a female dog'
複製代碼

它工做正常,可是代碼又長又難以維護。維護代碼的時候可能會浪費一些時間弄清楚右括號在哪裏。bash

想象一下,若是代碼具備更復雜的邏輯,將會發生什麼 —— 不少 if .. elseapp

咱們可使用三元運算符&&條件等來重構上述函數,但讓咱們使用多個return語句編寫更精確的代碼。函數

// good example

const printAnimalDetails = ({ type, name, gender } = {}) => {
    if (!type) return 'No animal type';
    if (!name) return 'No animal name';
    if (!gender) return 'No animal gender';

    return `${name} is a ${gender} ${type}`;
}

console.log(printAnimalDetails()); // 'No animal type'

console.log(printAnimalDetails({ type: dog })); // 'No animal name'

console.log(printAnimalDetails({ type: dog, gender: female })); // 'No animal name'

console.log(printAnimalDetails({ type: dog, name: 'Lucy', gender: 'female' })); // 'Lucy is a female dog'
複製代碼

另外一個例子:學習

// bad example

function printVegetablesWithQuantity(vegetable, quantity) {
    const vegetables = ['potato', 'cabbage', 'cauliflower', 'asparagus'];

    // condition 1: vegetable should be present
    if (vegetable) {
        // condition 2: must be one of the item from the list
        if (vegetables.includes(vegetable)) {
            console.log(`I like ${vegetable}`);

            // condition 3: must be large quantity
            if (quantity >= 10) {
                console.log('I have bought a large quantity');
            }
        }
    } else {
        throw new Error('No vegetable from the list!');
    }
}

printVegetablesWithQuantity(null); //  No vegetable from the list!
printVegetablesWithQuantity('cabbage'); // I like cabbage
printVegetablesWithQuantity('cabbage', 20);
// I like cabbage
// I have bought a large quantity
複製代碼

上面例子有如下問題測試

  • 第一層if用於過濾無效條件
  • 3層嵌套的if語句

解:ui

發現無效條件時儘快返回spa

// good

function printVegetablesWithQuantity(vegetable, quantity) {

    const vegetables = ['potato', 'cabbage', 'cauliflower', 'asparagus'];

    // condition 1: throw error early
    if (!vegetable) throw new Error('No vegetable from the list!');

    // condition 2: must be in the list
    if (vegetables.includes(vegetable)) {
        console.log(`I like ${vegetable}`);

        // condition 3: must be a large quantity
        if (quantity >= 10) {
            console.log('I have bought a large quantity');
        }
    }
}
複製代碼

3. 使用對象

// bad example

function printFruits(color) {
    // use switch case to find fruits by color
    switch (color) {
        case 'red':
            return ['apple', 'strawberry'];
        case 'yellow':
            return ['banana', 'pineapple'];
        case 'purple':
            return ['grape', 'plum'];
        default:
            return [];
    }
}

printFruits(null); // []
printFruits('yellow'); // ['banana', 'pineapple']
複製代碼

上面的代碼沒有錯,可是仍然很冗長。

使用object映射更簡潔的語法能夠實現相同的結果:

// good example

const fruitColor = {
    red: ['apple', 'strawberry'],
    yellow: ['banana', 'pineapple'],
    purple: ['grape', 'plum']
};

function printFruits(color) {
    return fruitColor[color] || [];
}

// 或者使用 Map,Map 是自 ES2015 起可用的對象類型

const fruitColor = new Map()
    .set('red', ['apple', 'strawberry'])
    .set('yellow', ['banana', 'pineapple'])
    .set('purple', ['grape', 'plum']);

function printFruits(color) {
    return fruitColor.get(color) || [];
}

// 或者使用 Array.filter,同樣能夠實現

const fruits = [
    { name: 'apple', color: 'red' },
    { name: 'strawberry', color: 'red' },
    { name: 'banana', color: 'yellow' },
    { name: 'pineapple', color: 'yellow' },
    { name: 'grape', color: 'purple' },
    { name: 'plum', color: 'purple' }
];

function printFruits(color) {
    return fruits.filter(fruit => fruit.color === color);
}
複製代碼

4. 默認參數和解構

使用JavaScript時,咱們老是須要檢查 null / undefined 值並賦值,不然編譯會中斷。

// bad example

function printVegetableName(vegetable) {
    if (vegetable && vegetable.name) {
        console.log(vegetable.name);
    } else {
        console.log('unknown');
    }
}

printVegetableName(undefined); // unknown
printVegetableName({}); // unknown
printVegetableName({ name: 'cabbage', quantity: 2 }); // cabbage
複製代碼

解:

經過使用默認參數和結構來避免煩人的判斷條件

// good example

function printVegetableName({ name } = {}) {
    console.log(name || 'unknown');
}

printVegetableName(undefined); // unknown
printVegetableName({}); // unknown
printVegetableName({ name: 'cabbage', quantity: 2 }); // cabbage
複製代碼

5. 使用Array.everyArray.some等新語法糖

// bad example

const fruits = [
    { name: 'apple', color: 'red' },
    { name: 'banana', color: 'yellow' },
    { name: 'grape', color: 'purple' }
];

function test() {
    let isAllRed = true;

    // condition: all fruits must be red
    for (let f of fruits) {
        if (!isAllRed) break;
        isAllRed = (f.color == 'red');
    }

    console.log(isAllRed); // false
}
複製代碼

代碼太長了!咱們能夠減小行數,使用Array.every

// good example

const fruits = [
    { name: 'apple', color: 'red' },
    { name: 'banana', color: 'yellow' },
    { name: 'grape', color: 'purple' }
];

function test() {
    const isAllRed = fruits.every(f => f.color == 'red');
    console.log(isAllRed); // 全是紅色:false
}

// 以相似的方式,若是咱們要測試是否有紅色的水果,咱們可使用 Array.some 在一行中實現它。

const fruits = [
    { name: 'apple', color: 'red' },
    { name: 'banana', color: 'yellow' },
    { name: 'grape', color: 'purple' }
];

function test() {
    const isAllRed = fruits.some(f => f.color == 'red');
    console.log(isAnyRed); // 包含紅色:true
}
複製代碼

更多數組語法可查看 MDN Javascript Array Docs,不一一展開。

6. ??

彩蛋

看看下面代碼,你必定有過這樣的煩惱,特別是接口過來鬼知道怎樣的數據

const car = {
    model: 'Fiesta',
    manufacturer: {
        name: 'Ford',
        address: {
            street: 'Some Street Name',
            number: '5555',
            state: 'USA'
        }
    }
}

const model = car && car.model || 'default model';

const street = car && car.manufacturer && car.manufacturer.address && car.manufacturer.address.street || 'default street';

const phoneNumber = car && car.manufacturer && car.manufacturer.address && car.manufacturer.phoneNumber;

console.log(model) // 'Fiesta'
console.log(street) // 'Some Street Name'
console.log(phoneNumber) // undefined

const isManufacturerFromUSA = () => {
    if (car && car.manufacturer && car.manufacturer.address && car.manufacturer.address.state === 'USA') {
        console.log('true');
    }
}

const isManufacturerFromUSA = () => {
    if (car && car.manufacturer && car.manufacturer.address && car.manufacturer.address.state === 'USA') {
        console.log('true');
    }
}

checkCarManufacturerState() // 'true'
複製代碼

您能夠清楚地看到,在對象結構複雜且不受控的狀況下,這會變得多麼混亂。

有一些第三方庫,例如lodash或idx具備本身的功能。例如lodash有_.get方法。

可是,JavaScript語言自己引入的此功能很是酷。

這些新功能的工做方式以下:

const model = car ?.model ?? 'default model';

const street = car ?.manufacturer ?.address ?.street ?? 'default street';

const isManufacturerFromUSA = () => {
    if (car ?.manufacturer ?.address ?.state === 'USA') {
        console.log('true');
    }
}
複製代碼

這看起來更漂亮,更易於維護。它已經在 TC39 stage 3 規範定製中。

很快就能用上這爽到飛起的寫法了!

結語

讓咱們學習並嘗試新的技巧和技術,編寫更乾淨,更可維護的代碼。

材料

Tips to write better Conditionals in JavaScript

相關文章
相關標籤/搜索