Dynamically adding cases to a switch
You can use Object
for switch cases. One of the advantages of using Object
instead of Array
for the case is that it drastically reduces errors caused by wrong indexes in Array
. Using Object
for cases, you can also extract your case values into another script. This helps for Single Responsibility Principle by concerning you only implementing business logic inside switch cases instead of worrying about maintaining the right case values.
const OP = {
ADD: 'ADD',
MULTIPLY: 'MULTIPLY',
};
const choice = 'ADD';
switch (choice) {
case OP.ADD:
console.log('You chose add');
break;
case OP.MULTIPLY:
console.log('You chose multiply');
break;
default:
console.log('Operation is not defined');
}
You can use object with callback functions instead:
// you can have initial casses
var callbacks = {
'something': [() => 42]
};
// and you can create new entry with this function
function add(_case, fn) {
callbacks[_case] = callbacks[_case] || [];
callbacks[_case].push(fn);
}
// this function work like switch(value)
// to make the name shorter you can name it `cond` (like in scheme)
function pseudoSwitch(value) {
if (callbacks[value]) {
callbacks[value].forEach(function(fn) {
fn();
});
}
}
and you can add new entry using:
add('something', function() {
// case for something
});
NOTE:
You can also modify this to work a little bit different than the original switch because you can have a function that returns a value and use a switch-like expression (like in Scheme where everything is an expression that returns a value):
const value = cond(42);
Writing this type of pseudoSwitch/cond function is left as an exercise to the reader.
NOTE 2:
By default objects in JavaScript use strings as keys and if you need to use something that can't be easily converted to a string, like objects (that will be converted to [Object object]
) then you can use Map object that accepts anything as keys. Note that symbols work differently and they are not converted to a string when used as key in array.
This was the best/simpler solution for my needs:
const customSwitch = [
{
condition: 'case1',
fn() { /* Do stuff if case1 */ },
}, {
condition: 'canBeChangedAnytime',
fn() { /* Do stuff if case2 */ },
},
...adSomeCasesDynamycallyHere,
]
// edit a condition:
customSwitch[0].condition = 'changed';
// use the switch
for (const { condition, fn } of customSwitch) {
if (myValue === condition) {
fn();
break;
}
}
customSwitch
, may have the form of an object, which may improve readability. Eg: customSwitch = { myCond: { condition, fn }}
You can click the above snippet to see it working ;)
const customSwitch = [ {
condition: 38,
fn: val => $("body").append(val === 38 ? 'UP' : 'RIGHT') + ' ',
}, {
condition: 40,
fn: val => $("body").append((val === 40 ? 'DOWN' : 'LEFT')+ ' ') ,
}]
$('#option1').click(function () {
customSwitch[0].condition = 38
customSwitch[1].condition = 40
});
$('#option2').click(function () {
customSwitch[0].condition = 39
customSwitch[1].condition = 37
});
$(window).keydown(function (e) {
for (const { condition, fn } of customSwitch) {
if (e.keyCode === condition) {
fn(e.keyCode);
break;
}
}
});
.btn {
cursor:pointer;
padding:5px;
border-radius:5px;
background-color:#3C0;
margin-top:5px;
width:150px;
text-align:center;
display:inline-block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Press the four arrow keys:<br>
-if you click <b>option1</b> the switch will recognize UP and DOWN<br>
-if you click <b>option2</b> the switch will recognize LEFT and RIGHT<br>
<div id='option1' class='btn'>OPTION 1</div>
<div id='option2' class='btn'>OPTION 2</div>
<hr>