Depends on the target device and what you do with the objects and how often. I found out the hard way why using sprites as tiles for a game with Z-levels is bad, especially when you have a couple thousand of them. But I digress. And you want infinite inventories anyway.
But generally I would recommend against having such a thing as an item object for each item when not necessary and that is the approach I took when doing inventory systems in some of my attempts at such.
What I do instead is the following. Store items only in an array, they exist only as a columns in arrays. An array with many rows mind you as it contains general information such as item type, sub-type, weight, size, sprite, name and description. It also has a bunch of rows dedicated to "special" data. In those rows I store coma separated value strings that are different for each item type. For example weapons have different strings, armor has differently formatted strings etc.
So how do I fire a gun a with that or equip body armor? There are two approaches I am considering now but I will most likely use the second one (I used the first in the past):
1) Have a weapon object created and assigned to the player, just one. It is in reality a container, a shapeshifter that takes the properties of whatever weapon is currently equipped by the assigned parent player or NPC object. Whenever the weapon is changed, a function will reset all its variables and load new values. The new values will be taken from the "special" data strings. The logic of the function will retrieve the special string and next, using the tokenat expression, load the weapon properties into the weapon object. Next I use the weapon object in the events as I please.
2) Do not have a separate object altogether, store all equipped weapon data as variables of the NPC object. Otherwise it will work the same as approach 1.
Now you asked how Final Fantasy etc. manage infinite items. They don't use object obviously for each item. When you look at an inventory you are looking at a graphical representation of an array. What they do, what I do and indeed what even such advanced business software such as SAP do (at least for multiple single value selection fields) is that they have a set number of list position objects or slot objects. Each slot is assigned an ordered position from 0 to X.
Next what they do is store the index of the first object in the table/inventory they are showing, let's call it "i" for short. When you scroll the list a function is called updating the index of the currently displayed first object. Next the list is refreshed and the code uses a loop to put the data of item "i" into the first slot object, "i"+1 into the second slot object etc. i=4 would mean that object with index 4 (so the 5th row) of the inventory array would be shown first (top of the list/first slot).
So you only need slot objects to show the item, as many as fit in the inventory window you designed. They will never change position, they will only change their appearance.
Bah, if you are using only a text based inventory without any item icons or anything like earlier FF games did, you could do it with a single text object. You would just need to know how many rows you can fit in the text and how much text in a row (I recommend using monospace fonts for that, which is also what systems displaying lots of lists and tables such as SAP do).
It would look like:
set text as array.at(i,0) [0 would be the y index of the item name in this example]
loop for 1 to number of rows
append text [newline&array.at(i+loopindex(),0)]
However making things such as highlighting the selected item, selecting it with clicking etc. would require additional objects.
tl;dr version store the data that is needed as an object now as an object, keep everything that you need later in arrays.