This is a collection of alternatives to using if and other conditional block statements in plain Javascript without module or library dependencies.
Some reasons to consider alternatives:
- boost immutability: because 
constis scope-level, it is unusable in functions usingifexcept within the blocks -- for assignment,letorvarare the only options, which are mutable - quality of code life: 
ifis block statement that has a tendency to beget nesting block statements ad infinitum, and become progressively harder to read as they are added to - avoid refactoring later: many 
ifs can usually indicate you really need to break your functions down further, and that your function is doing too much at once - often it should really just be a function: because it is a block-level element, the block can easily grow into something that clearly should be a function, or even many functions
 - control side-effects: 
switchstatements can easily "leak" when missing abreakstatement, and create "branches" of code without braces, hiding these branches somewhat - testability: each 
ifcreates a logical branch that cannot be independantly tested - functional: if functional programming is something you want to do more of, you'll generally want less 
ifandlet - be safer with type: when you convert an 
ifinto a function, you can test for types in TypeScript and Flow 
The following examples may or may not adhere to a functional programming style, but can be used as a stepping stone towards more functional code. I tend to prefer functional, but it can be a huge leap to go straight to pure functional.
Each example is a very basic form of a common conditional pattern. These suggestions are meant to give you some ideas of alternatives.
Some examples, such as the "incongruent if/else" examples could be considered antipatterns and are themselves likely to be considered by most as poorly-formed if statements.
let y;
if (x === 1) {
    y = 2;
}Basic, returns y as false for default.
// ternary with false default
const y = x === 1 ? 2 : false;Similar, but has a reusable function that can be memoized.
// functional ternary
const checkX = x => (x === 1 ? 2 : false);
const y = checkX(x);let y;
if (x === 1) {
    y = 2;
} else {
    y = 1;
}Very basic, readable. Allows y to be a const.
// ternary assignment
const y = x === 1 ? 2 : 1;Very similar, but reusable and memoizable.
// functional ternary
const checkX = x => (x === 1 ? 2 : 1);
const y = checkX(x);let y;
if (x === 1) {
    y = 2;
} else if (x === 2) {
    y = 17.3;
} else {
    y = 1;
}switch (x) {
    case 1:
        y = 2;
        break;
    case 2:
        y = 17.3;
        break;
    default:
        y = 1;
}Use an object to store values as key-value pairs.
// key-value pair list with default
const vals = {
    1: 2,
    2: 17.3,
    default: 1
};
const y = x in vals ? vals[x] : vals.default;Very similar, and prevents namespace collisions: use a symbol for your default value key. (The example above with default key would likely misbehave if x ever had a value called 'default'.)
// key-value pair list with symbol
// this avoids namespace collision in key names
// note that `$$` is merely a naming style suggestion for Symbols, it is not a requirement at all
const $$defaultSymbol = Symbol();
const vals = {
    1: 2,
    2: 17.3,
    [$$defaultSymbol]: 1
};
const y = x in vals ? vals[x] : vals[$$defaultSymbol];Or, use an array to store the values. Works only if dealing with low numbers.
// value list accessed by index
const vals = [null, 2, 17.3];
const y = vals[x] || 1;Use a getter inside a constant function expression as a means of looking up a key-value pair. Allows for memoization, though uses the dreaded this keyword...
// getter
const vals = x => ({
    1: 2,
    2: 17.3,
    get value() {
        return this[x] || 1;
    }
});
const y = vals(x).value;Constant function expression returning a lookup table: zeroth index is the condition, first index is the result.
// conditionals table
const condTable = x => [
    [x === 1, 2],
    [x === 2, 17.3],
    [true, 1]
];
const y = condTable(x)
    .find(a => (a[0] ? a[1] : false))
    .pop();let y;
if (x === 1) {
    y = 2;
} else if (x === 2) {
    y = 17.3;
} else if (z === 4) {
    y = 19.2;
{ else if (w === 'something') {
    y = 22;
} else {
    y = 1;
}Another constant function expression returning a lookup table, this time taking an array as a parameter. The array param allows for memoization of the table.
// conditionals table with array param
// array-based param allows for memoization if need be
const condTable = ([x, z, w]) => [
    [x === 1, 2],
    [x === 2, 17.3],
    [z === 4, 19.2],
    [w === 'something', 22],
    [true, 1]
];
const y = condTable([x, z, w])
    .find(a => (a[0] ? a[1] : false))
    .pop();What if not just the conditions are mixed, but the results too?
let y;
let j;
if (x === 1) {
    y = 2;
} else if (x === 2) {
    y = 17.3;
} else if (z === 4) {
    y = 19.2;
{ else if (w === 'something') {
    y = 22;
{ else if (w === 'something else') {
    j = 5;
} else {
    y = 1;
}Similar to conditionals table, use the table to execute functions rather than assign value.
// results are functions, pass everything into params that might be needed
let y, j;
const setY = v => y = v;
const setJ = v => j = v;
const condTable = ([x, z, w]) => [
    [x === 1, setY, 2],
    [x === 2, setY, 17.3],
    [z === 4, setY, 19.2],
    [w === 'something', setY, 22],
    [w === 'something else', setJ, 5],
    [true, setY, 1]
];
condTable([x, z, w])
    .find(a => (a[0] ? a[1](a[2]) : false));let y, z;
if (x === 1) {
    y = 2;
    if (w > 4) {
        z = 1;
    }
} else {
    y = 1;
    if (w < 4) {
        z = 2;
    }
}Take each layer and transpose each if to a function, or assignment.
const fn1 = () => {
    y = 2;
    z = w > 4 ? 1 : z;
};
const fn2 = () => {
    y = 1;
    z = w < 4 ? 2 : z;
};
const assignVals = x =>
    x === 1
        ? fn1()
        : fn2();