JavaScriptで優雅に条件判断を行う
14331 ワード
この文章は翻訳文です.
原文のリンク:https://dev.to/hellomeghna/tips-to-write-better-conditionals-in-javascript-2189
条件語句とは何ですか?
どんなプログラミング言語であっても、コードの中には判断が欠かせないし、入力した条件によって異なる操作を実行します.
例えば、あるゲームでは、プレイヤーのライフが0以下の場合、ゲームは終了します.天気予報アプリでは、朝に太陽の写真を表示し、夜に星と月の写真を表示します.本論文ではJavaScriptで類似の条件処理を行う方法を紹介します.
JavaScriptを書くと、多くの条件を含めたコードがたくさん書かれます.これらの条件語句は、最初はよく理解できたかもしれませんが、しばらくするとめちゃくちゃになります.実は
ここでは清潔で優雅な条件の判断についてのアドバイスがあります.
目次 Aray.includes 早期終了し、 に戻る. Switch式 をObjectで巡回またはMapで置換します.は、デフォルトパラメータと構成解除値 を使用する. Aray.everyおよびAray.someを使用して、すべておよび部分的条件判断 を実現する. Use Optional Chining and Nullish Coalescing 1.アラy.includes
複数の条件があれば
たとえば:
ソリューション:
2.早期退出と返却
これはとてもクールなテクニックです.コードをシンプルに見せてくれます.私は仕事の初日から教えられました.条件判断には
前の例のために条件を追加します.アニメーションが単なる
だから今の需要は次のようになりました.もしanimalがないならば、1つの誤りを投げます. アニマルのタイプ をプリントアウトしました.アニマルの名前をプリントしました. アニマルのタイプ をプリントアウトしました.
上のコードはバグがないですが、長すぎてメンテナンスが難しいです.新人は午前中にどの括弧を探しに来ますか?もう少し論理が複雑なら、
別の例:ペア です.レベルネスト 次に私達のコースを紹介します.
ですから、私たちの目標はネストを撲滅し、早めにリターンすることです.でも、リターンがいいです.「カップを貪る」こともできません.
3.SwitchをObjectで巡回またはMapで置換する表式
この例を見てみましょう.色に基づいて果物をプリントアウトしたいです.
私たちはJavaScriptを書く時、常に
私たちも関数のパラメータにデフォルト値
5.Aray.everyとAray.someを使って、すべてと一部の条件判断を実現する.
私は配列のこれらの方法を使ってコードの行数を減らすことができます.下のコードの中で果物は全部赤いかどうかを判断したいです.
この2つの機能はJavaScriptにおいて非常に有用である.しかし、今のところサポートがあまりよくないので、バベルを使ってコンパイルをしなければなりません.
以下は例です.
次はその例です.
締め括りをつける
これらの提案を使って、清潔でメンテナンスしやすいコードを書いてみましょう.長い条件判断のため、あと数ヶ月であなた自身が読めなくなります.
原文のリンク:https://dev.to/hellomeghna/tips-to-write-better-conditionals-in-javascript-2189
条件語句とは何ですか?
どんなプログラミング言語であっても、コードの中には判断が欠かせないし、入力した条件によって異なる操作を実行します.
例えば、あるゲームでは、プレイヤーのライフが0以下の場合、ゲームは終了します.天気予報アプリでは、朝に太陽の写真を表示し、夜に星と月の写真を表示します.本論文ではJavaScriptで類似の条件処理を行う方法を紹介します.
JavaScriptを書くと、多くの条件を含めたコードがたくさん書かれます.これらの条件語句は、最初はよく理解できたかもしれませんが、しばらくするとめちゃくちゃになります.実は
if/else
よりも良い方法で条件判断を実現しています.ここでは清潔で優雅な条件の判断についてのアドバイスがあります.
目次
複数の条件があれば
Array.includes
を使用することができる.たとえば:
function printAnimals(animal) {
if (animal === 'dog' || animal === 'cat') {
console.log(`I have a ${animal}`);
}
}
console.log(printAnimals('dog')); // I have a dog
上のコードはよさそうです.二つの小動物を検査するだけです.しかし、私たちはユーザーが何を入力するかは分かりません.もし動物のタイプが多くなったら?||
条件を拡張して判断し続けると、需要を満たすためにコードが維持されにくくなり、乱雑に見えるようになります.ソリューション:
Array.includes
を使って上記のコードを再構築できます.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.早期退出と返却
これはとてもクールなテクニックです.コードをシンプルに見せてくれます.私は仕事の初日から教えられました.条件判断には
early exit
が必要です.前の例のために条件を追加します.アニメーションが単なる
string
ではなく、特定の属性を持つobject
である場合.だから今の需要は次のようになりました.
const printAnimalDetails = animal => {
let result; // declare a variable to store the final value
// 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'
上のコードについてどう思いますか?上のコードはバグがないですが、長すぎてメンテナンスが難しいです.新人は午前中にどの括弧を探しに来ますか?もう少し論理が複雑なら、
if/else
はもっと多いです.上記のコードは?:
、$$
演算子などで再構成できます.でも、私は(はははは…)ません.上のコードを再構築するために何度もreturnを使いました.const printAnimalDetails = ({type, name, gender } = {}) => {
if(!type) return 'No animal type';
if(!name) return 'No animal name';
if(!gender) return 'No animal gender';
// Now in this line of code, we're sure that we have an animal with all //the three properties here.
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'
再構成版では、オブジェクトの構成値と関数パラメータのデフォルト値も使用されます.デフォルトの値の役割は、私たちが通信していなければ、エラーがないということです.別の例:
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/else
は、利用できない条件をフィルタリングするために使用されるif
.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');
}
}
}
このように再構成した後に、私達は1階のif
の入れ子が足りなくなりました.あなたの条件が比較的に長いと判断した時、このコードスタイルは特に使いやすいです.if
ネストをさらに減らすことができます.条件を反転してreturn
を採用します.以下は具体的な実現です.function printVegetablesWithQuantity(vegetable, quantity) {
const vegetables = ['potato', 'cabbage', 'cauliflower', 'asparagus'];
if (!vegetable) throw new Error('No vegetable from the list!');
// condition 1: throw error early
if (!vegetables.includes(vegetable)) return;
// condition 2: return from the function is the vegetable is not in
// the list
console.log(`I like ${vegetable}`);
// condition 3: must be a large quantity
if (quantity >= 10) {
console.log('I have bought a large quantity');
}
}
第二の条件を逆にすることで、コードにはif
の入れ子が見えなくなりました.この技法は、多くの条件があるときに判断し、あるものを満たすときに、残りの論理処理を行わないようにするのに適しています.ですから、私たちの目標はネストを撲滅し、早めにリターンすることです.でも、リターンがいいです.「カップを貪る」こともできません.
3.SwitchをObjectで巡回またはMapで置換する表式
この例を見てみましょう.色に基づいて果物をプリントアウトしたいです.
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を使って同じ効果を実現できます.// use object literal to find fruits by color
const fruitColor = {
red: ['apple', 'strawberry'],
yellow: ['banana', 'pineapple'],
purple: ['grape', 'plum']
};
function printFruits(color) {
return fruitColor[color] || [];
}
もちろんMapも使えます.// use Map to find fruits by color
const fruitColor = new Map()
.set('red', ['apple', 'strawberry'])
.set('yellow', ['banana', 'pineapple'])
.set('purple', ['grape', 'plum']);
function printFruits(color) {
return fruitColor.get(color) || [];
}
MapはES 2015(Es 6)の文法です.互換性に注意してください.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
をチェックして、パラメータに対してデフォルト値を賦課します.そうでないとエラーが発生します.function printVegetablesWithQuantity(vegetable, quantity = 1) {
// if quantity has no value, assign 1
if (!vegetable) return;
console.log(`We have ${quantity} ${vegetable}!`);
}
//results
printVegetablesWithQuantity('cabbage'); // We have 1 cabbage!
printVegetablesWithQuantity('potato', 2); // We have 2 potato!
もしvegetable
がオブジェクトだったら?私たちはそれにデフォルトの割り当てができますか?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
上記の例では、vegetableに利用可能な値があれば、そのnameをプリントアウトします.そうでなければunknow
をプリントします.if (vegetable && vegetable.name) {}
の代わりに、デフォルト値と構成解除値を使用することができます.// destructing - get name property only
// assign default empty object {}
function printVegetableName({name} = {}) {
console.log (name || 'unknown');
}
printVegetableName(undefined); // unknown
printVegetableName({ }); // unknown
printVegetableName({ name: 'cabbage', quantity: 2 }); // cabbage
name
属性が必要ですので、{name}
を解凍して、name
変数を使用できます.これでvegetable.name
を使う必要がなくなります.私たちも関数のパラメータにデフォルト値
{}
を設定しました.そうでないとprintVegeTable(undefined)
を実行するとCannot destructure property name of undefined or null
にエラーが発生します.5.Aray.everyとAray.someを使って、すべてと一部の条件判断を実現する.
私は配列のこれらの方法を使ってコードの行数を減らすことができます.下のコードの中で果物は全部赤いかどうかを判断したいです.
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
}
コードが長すぎます.私たちはAray.everyを変えてみてもいいです.const fruits = [
{ name: 'apple', color: 'red' },
{ name: 'banana', color: 'yellow' },
{ name: 'grape', color: 'purple' }
];
function test() {
// condition: short way, all fruits must be red
const isAllRed = fruits.every(f => f.color == 'red');
console.log(isAllRed); // false
}
同じように、一部の果物が赤色であると判断したいなら、私達はアラy.someで実現できます.const fruits = [
{ name: 'apple', color: 'red' },
{ name: 'banana', color: 'yellow' },
{ name: 'grape', color: 'purple' }
];
function test() {
// condition: if any fruit is red
const isAnyRed = fruits.some(f => f.color == 'red');
console.log(isAnyRed); // true
}
6.Use Optional Chining and Nullish Coalescingこの2つの機能はJavaScriptにおいて非常に有用である.しかし、今のところサポートがあまりよくないので、バベルを使ってコンパイルをしなければなりません.
undefined
は、中間層をスキップして、ツリー構造がある属性を含むかどうかを確認することができるようにする.Optional chaining
は、およびnullish coalescing
は、変数にデフォルト値を割り当てて使用する.以下は例です.
const car = {
model: 'Fiesta',
manufacturer: {
name: 'Ford',
address: {
street: 'Some Street Name',
number: '5555',
state: 'USA'
}
}
}
// to get the car model
const model = car && car.model || 'default model';
// to get the manufacturer street
const street = car && car.manufacturer && car.manufacturer.address &&
car.manufacturer.address.street || 'default street';
// request an un-existing property
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');
}
}
checkCarManufacturerState() // 'true'
このようにコードを書くのはどんなに乱れているかを見ることができます.すでにいくつかの第三者ライブラリがあります.例えば、Optional chaining
またはlodash
は自分の関数を持っています.この操作を簡単にします.例えばidx
のlodash
.しかし、JavaScriptがそのままこの操作をサポートしてくれるといいです.次はその例です.
// to get the car model
const model = car?.model ?? 'default model';
// to get the manufacturer street
const street = car?.manufacturer?.address?.street ?? 'default street';
// to check if the car manufacturer is from the USA
const isManufacturerFromUSA = () => {
if(car?.manufacturer?.address?.state === 'USA') {
console.log('true');
}
}
このコードはかなり綺麗に見えます.メンテナンスも簡単です.この特性はすでに_.get
の提案の中にあります.私たちはあとで使えます.締め括りをつける
これらの提案を使って、清潔でメンテナンスしやすいコードを書いてみましょう.長い条件判断のため、あと数ヶ月であなた自身が読めなくなります.