Building a UI to fetch list of features and edit them
Syntax and Compatibility

Most browsers will balk at the redefinition of a function parameter using the let keyword here:

// builds the list of features
function buildFeaturesList(featureList) {
    let featureList = featureList || activeFeatures



Chrome: Uncaught SyntaxError: Identifier 'featureList' has already been declared
Firefox: SyntaxError: redeclaration of formal parameter featureList
IE11: Let/Const redeclaration


This can be corrected by replacing let with var in this instance. Note that the primary difference between let and var is that let is block-scoped, while var is function-scoped. Since the block containing this variable declaration is a function anyway, you don't gain any advantage by using let.

IE11 also does not yet support arrow (=>) syntax for lambda functions, but if you don't have to support such users you can ignore that problem.

Avoid modifying innerHTML directly

Direct modification of an element's innerHTML property should be avoided whenever possible. It has performance drawbacks (forcing the browser to re-evaluate the DOM with each modification) and it can create memory leaks (when code retains references to elements that have been destroyed by overwriting their HTML).

Instead, consider these approaches:

Clearing innerHTML

To clear the innerHTML without creating memory leaks, instead of features.innerHTML = ''; you can use a loop to remove all child nodes:

while(features.childNodes.length &gt; 0){
    features.removeChild(features.childNodes[features.childNodes.length - 1]);
}


A for loop can be more efficient since you can avoid accessing the childNodes.length property multiple times.

for(let i = features.childNodes.length-1; i &gt;= 0; i--){
    features.removeChild(features.childNodes[i]);
}


Appending to innerHTML

To append to innerHTML without forcing the DOM to reload with every change, you can use element.insertAdjacentHTML().

For example, instead of list.innerHTML += stringValue use list.insertAdjacentHTML("beforeend",stringValue):

list.insertAdjacentHTML("beforeend",
    '&lt;li id="' + item.feature + '"&gt;&lt;span class="checkbox"  data-feature="' 
    + item.feature + '" checked="false"&gt;&lt;/span&gt; &lt;span class="feature-name"&gt;' 
    + item.feature + '&lt;/span&gt; &lt;ul data-feature="' + item.feature + '" class="variant-list"&gt;' 
    + injectVariants(item.variants) + '&lt;/ul&gt;&lt;/li&gt;'
);


Note that you might also want to consider element.appendChild() which lets you append any HTML element by its reference, such as the reference obtained when you create an element using document.createElement(). That approach is more versatile (you can retain references to the elements in code and attach event handlers to the elements programmatically) but will be slightly slower than element.insertAdjacentHTML().