The main difference is that the salt is not assumed unknown to the attacker, but the key is. An additional difference is that salts are supposed to vary; if you hash three passwords within the same system, then you should use three distinct salt values, whereas keys are reused.
Another way of seeing salts is to consider that you do not have one hash function, but a complete family. The "salt" is then a designation for the actual hash function that you are using on a specific instance. Each instance should use its own hash function, i.e. its own salt value, to deter attack parallelism (precomputed tables can be thought of as a kind of parallelism), precisely because all the hash functions in the family are public and the attacker knows which one you are using.
Conversely, if you can keep the salt "secret" then it is a key, and can be shared between instances; but since the security model is no longer the same, it is not guaranteed that a salt which is good as a salt would ensure security as a key. For instance, suppose a system where the salt is the concatenation of a unique server identifier (say, the server fully qualified domain name) and the current time expressed in milliseconds since a conventional epoch (we assume that no two salts are generated within the same millisecond, and that time management ensures a monotonic clock even if the clock is reset or adjusted). This yields good salts: such salts are unique worldwide (unique across all instances of all servers in the world) and efficient at preventing parallel attacks. However, as keys, they would be extremely poor because the server's hostname and the current time are public information, and the attacker knows them.