I would create an object for each type of weapon that that has similar properties. For example, a single object might contain swords and daggers, and another might contain bows. Each frame in that object would be the variations of looks of that type of weapon, basically reskins. This would separate out your total weapons into several spritesheets, aiding in the loading issue.
As for your reference/object id problem, you can use Constants if you like to refer to your object by name rather than number
ie.
Rapier=72
ChickenSlicer=73
You can use these in function, or anywhere -
On Call EquipBlade(ChickenSlicer) - Create BladeObject, Set BladeObject animation frame to (param0). This would create the object and set it to frame 73. Constants are also easy to change in case your animation frame changes, besides which it is also pretty easy to reorder your frames in the editor.
If all of your weapons have unique properties, it would make a lot of sense to use an array to store the data. When you get to a huge amount of unique weapons, it becomes much more manageable to keep track/edit in a spreadsheet program, and import it via project files as a CSV or XML to parse into an array on load.
If you're worried about loading a whole bunch of weapons you don't need at once, again, you can use project files to load only the sprites you need on demand at runtime.
Basically if you're objective is to create objects via expressions and strings, your best bet still is to utilize constants and animation frames.
In the end, you mention best practices, but it is a pretty common advice here regarding optimization - unless you can notice a difference in practice, it is best not to worry about it and focus first on your game mechanics. I don't think it would be a big deal/difference to download 10 or 30 or 50 weapon sprites/frames in one object versus splitting them into 2 or 10 or 50 different objects. How many unique weapons do you have?