JavaScriptの関数で引数に値を渡すときと参照先を渡すときの挙動の差

2021年2月4日JavaScript

とてもバグに繋がりやすいJavaScriptの関数で引数に値を渡すときと参照先を渡すときの挙動の差の具体例をみてみましょう。

JavaScriptの関数で引数に値を渡すときと参照先を渡すときの挙動の差

まずは下の具体例をみてみましょう。

//Arguments. value vs reference

const ticket = 'tr442';
const yamada = {
  name: 'yamada taro',
  passcode: 2928732
}

const checkIn = function(ticketNum, customer) {
  ticketNum = 'ir789';
  customer.name = customer.name + '様';

  if(customer.passcode === 2928732) {
    console.log('ご来場ありがとうございます。')
  } else {
    console.log('パスコードに誤りがあります。');
  }
}

checkIn(ticket, yamada); //ご来場ありがとうございます。
console.log(ticket);//tr442
console.log(yamada);//{name: "yamada taro様", passcode: 2928732}

//下と同じことが起こっている
// const ticketNum = ticket;
// const customer = yamada;

const newPasscode = function(person) {
  person.passcode = Math.trunc(Math.random() * 100000000);
}
newPasscode(yamada);
checkIn(ticket, yamada);//パスコードに誤りがあります。

コンソールに出力された値に関して。なぜticketは関数内の変更通りになっておらず、一番上で定義した値が返されているのでしょうか?
また、なぜyamadaは関数内で変更された値である「様」がついているのでしょうか?
ふたつで挙動が異なります。
それは、プリミティブ型とオブジェクト型の違いと全く同じで、ticketと関数内のticketNumは全く別の変数となります。
しかし、yamadaとcustomerは同じところを参照しているため、一方が変更されるともう一方も変更されます。
値(value)を渡しているのか、参照先(reference)を渡しているのか注意する必要があります。JavaScriptは参照先(reference)の値を渡しません。