Lucas, ótima pergunta — de verdade. Isso que você estranhou é um dos pontos mais importantes da lógica de programação, então vale parar e entender com calma.
Quando você escreve:
function apresentarPessoa(p) {
o p não é um objeto específico. Ele é só um nome de variável, um apelido que a função usa para se referir ao valor que ela vai receber. Poderia ser p, x, dados, pessoa… o nome não importa. O que importa é o valor que vai chegar ali.
Agora olha para essa linha:
apresentarPessoa(pessoa)
Aqui você está dizendo: “pegue o objeto que está guardado na variável pessoa e entregue ele para a função”. Quando isso acontece, o JavaScript associa esse valor ao parâmetro da função. Internamente, é como se fosse feito algo assim:
p = pessoa
Por isso, dentro da função, você usa p.nome, p.idade e p.profissao. Lá dentro não existe a variável pessoa, existe apenas o parâmetro p, que agora aponta para o mesmo objeto.
Um paralelo ajuda bastante. Pensa nesse exemplo:
function cumprimentar(nome) {
console.log(`Oi ${nome}`);
}
cumprimentar("Lucas");
A função não sabe que fora dela o valor é "Lucas". Ela só sabe que recebeu alguma coisa e chamou isso de nome. Com objetos funciona exatamente da mesma forma.
Então não é que o JavaScript “entendeu” sozinho quem é a pessoa. Você explicitamente passou o objeto pessoa para a função, e a função decidiu chamar esse valor de p.
Uma regra importante para guardar: o nome do parâmetro não precisa ser o mesmo nome da variável usada na chamada da função. O que importa é o valor que está sendo passado.
Se isso ainda parecer meio confuso, fica tranquilo. Esse entendimento costuma fazer clique aos poucos, e o fato de você ter parado para questionar isso mostra que está pensando do jeito certo.