Use a template library, do not concatenate strings and then just set HTML. Most template libraries will have safeguards in place to prevent XSS vulnerabilities. Even if the product name is always trusted to be non-malicious, it's still a dangerous anti-pattern.
XSS will eat your lunch. It breaks every safeguard there is, it even defeats 2 factor auth and lets the attacker adopt the identity and privileges of whoever has been exposed to the attack. It's prudent to be extra careful and never have code that looks like this.
If you had included just one more line of code it would have shown that this isn't a XSS issue at all:
var products = window.localStorage.getItem('products') || [], content = '';
If an attacker can set a localStorage value then they can already run JS making this entire attack vector completely superfluous. In order for your claimed attack to work someone has to have already conducted a XSS.
It is like talking about the risks of XSS within locally set cookies. It might technically be true but how do you set the cookie in order to later run the JS taken back out of it? Same issue here. How do you set the localstorage to give you back the JS to commit XSS, more XSS?
This is going to be very app specific but 'products' might be a list of products in a shopping cart and the products can be submitted to the store by third parties with arbitrary names. Then all an attacker has to do is to trick you into adding his evil product to your cart. Alternatively, products might be some kind of client side cache of products from the server and the attacker might not even have to trick you into adding something to your cart.
Of course it could be possible that the 'name' value is HTML and not TEXT and has already been pre-escaped. :)
Regardless of whether this is exploitable XSS or not this is probably a correctness issue. Stuff shouldn't start breaking when people start inputting '<' somewhere.
It's best to just not concatenate strings and then dump them into HTML. You can't know it's not an XSS issue unless you know how this ended up in localStorage to begin with. It could be untrusted user content that came from the server. But even if you do know where it came from, just don't do it. It's a bad habit and the day it burns you it might sting.
Assigning a variable as a pointer to an anonymous function:
var Box = function(a, b) {};
as opposed to the simpler:
function Box(a, b) {}
makes no sense. It is more verbose for zero benefit and makes all functions anonymous so you will never see that it is the Box function being called in your debuggers and profilers. If you want to enforce functions being declared before they are called, use JSLint (which you should be doing anyway.)
A lot of people use notation #1 to do namespacing by using objects, eg
var MyProject = {};
MyProject.func = function() {}
If you ever want to assign a function to an object, you might as well do it with global-scope functions. Most debuggers/profilers I am aware of can handle this notation well. If they don't, there is still the possibility of doing
+1 for the named function expression.
I really don't like pure function statements because of hoisting. You often end up seeing functions being used before they're defined which can lead to confusing bugs and hurts readability.
I also like that `var Box = function Box (a, b) {}` directly shows people who are new to JS that function declarations are nothing else than just assigning a function to a variable.
XSS will eat your lunch. It breaks every safeguard there is, it even defeats 2 factor auth and lets the attacker adopt the identity and privileges of whoever has been exposed to the attack. It's prudent to be extra careful and never have code that looks like this.
Use a template library, do not concatenate strings and then just set HTML. Most template libraries will have safeguards in place to prevent XSS vulnerabilities. Even if the product name is always trusted to be non-malicious, it's still a dangerous anti-pattern.