You need to use deferred rendering or pre-pass lighting. Some of the older fixed-function pipelines (read: no shaders) supported up to 16 or 24 lights - but that's it. Deferred rendering eliminates the light limit; but at the cost of a much more complicated rendering system.
Apparently WebGL supports MRT which is absolutely required for any form of deferred rendering - so it might be doable; I am just not sure how plausible it is.
Alternatively you could investigate Unity - which has deferred rendering right out of the box (with one of the more expensive licenses).
Another simple way to deal with this is to simply prioritize lights (maybe, based on the distance from the player and whether they are in the camera frustrum) and only enable the top 8. A lot of AAA titles managed to do this without much impact on the quality of the output (for example, Far Cry 1).
You could also look into pre-calculated lightmaps. Games like Quake 1 got a lot of mileage from these - and they can be quite small (bilinear filtering softens up stretched lightmaps quite nicely). Unfortunately pre-calculated excludes the notion of 100% dynamic lights, but it really does look great. You could combine this with your limit of 8 lights, so for example, only rockets or such would have a real light - but lights on the wall or such would be lightmaps.
Side note: You wan't to loop over them in a shader? Say goodbye to your performance. A GPU is not a CPU and isn't designed to work the same way that, for example, JavaScript does. Remember that each pixel you render (if even it gets overwritten) has to perform the loop - so if you take running at 1920x1080 and a simple loop that runs 16 times you are effectively running everything inside that loop 33177600 times. You graphics card will run a lot of those fragments in parallel, but those loops will still eat older hardware.