iptables does not prevent applications from opening TCP or UDP ports (because that could cause the applications to crash). Instead, it will prevent incoming packets from reaching the actual ports. If applied to outgoing traffic, it can stop the matching packets from being actually sent.
If you use
iptables ... -j DROP, the processing of any packets matching the rule is just stopped short, effectively causing the packet to be ignored with no response whatsoever. For legitimate TCP connections, this typically causes the sender to hang until the connection times out. But since the host must still answer to ARP requests, a scanner can still detect the presence of the host and can mark the port as "firewalled".
(If the scanner is not in the same network segment, it will not be able to directly observe ARP responses, but it can deduce their presence/absence by seeing whether or not the router of the target segment responds to connection attempts with ICMP "Host unreachable" error messages.
No "Host unreachable" errors + no TCP Resets/ICMP "Port unreachable"s = port is most likely firewalled.)
If you use
iptables ... -j REJECT, any packets matching the rule will be processed as if the destination port in question was never opened, regardless of the actual state of the port. This usually causes a TCP Reset or ICMP Error response packet to be sent back to the sender of the original packet, just like when attempting to connect to a closed port that has no firewall. This allows the sender to detect that the connection is being refused, so the connection attempt can fail quicker. For a scanner, such a result should be indistinguishable from a normal "closed" port.
If the sender has forged the source IP address of the original packet, the responses could be abused as part of a denial-of-service attack on another host, but modern OSs will deprioritize and/or rate-limit the sending of TCP Reset/ICMP Error packets by default, so this should not be a major concern.