[EffectiveJavaScript輪読会3]argumentsオブジェクトを書き換えない

GAS

どうも。つじけ(tsujikenzo)です。このシリーズでは2021年8月からスタートしました「ノンプロ研EffectiveJavaScript輪読会」についてお送りします。

前回のおさらい

前回は、「可変長引数関数を作るには、argumentsを使う」をお届けしました。

[EffectiveJavaScript輪読会3]可変長引数関数を作るには、argumentsを使う
どうも。つじけ(tsujikenzo)です。このシリーズでは2021年8月からスタートしました「ノンプロ研EffectiveJavaScript輪読会」についてお送りします。前回のおさらい前回は、「いくつでも引数をとれる関...

今回は、「argumentsオブジェクトを書き換えない」 をお届けします。

テキスト第3章「関数の扱い」の項目23に対応しています。

今日のアジェンダ

  • argumentsオブジェクトのおさらい
  • strictモード
  • argumentsオブジェクトのコピー

argumentsオブジェクトのおさらい

引き続きargumentについてです。もう少し紐解いてみましょう。なにかヒントがあるかもしれません。

argumentsオブジェクトとは、関数が受け取った引数を、暗黙的に関数内で参照できる、ローカル変数です。

繰り返しですが、アロー関数では使えません。配列のようにインデックスを取りますが、配列ではありません。

function myFunction3_23_01() {

  /**
   * 引数を操作する関数
  */
  const getArgument = function (parameter) {
    console.log(arguments); //{ '0': 100 }
    console.log(parameter); //100

    console.log(arguments[0] === parameter); //true
    console.log(arguments['0'] === parameter); //true

    //console.log(arguments.shift()); //TypeError: arguments.shift is not a function
  };

  getArgument(100);

}

strictモード

use strictモード下では、argumentsは予約語とみなされ、変数に使用できません。

同じような予約語に、implements, interface, let, package, private, protected, public, static, yield があります。

function myFunction3_23_02() {
  'use strict'

  let arguments; //SyntaxError: Unexpected eval or arguments in strict mode

}

use strictモード下では、argumentオブジェクトを固定することができます。

以下のように、引数を関数内で書き換えたとしても、argumentsオブジェクトに変更を及ぼしません。

function myFunction3_23_03() {
  'use strict'

  /**
   * 引数を操作する関数
  */
  const getArgument = function (parameter) {
    parameter = 200;

    console.log(arguments); //{ '0': 100 }
    console.log(parameter); //200

    console.log(arguments[0] === parameter); //false
    console.log(arguments['0'] === parameter); //false
  };

  getArgument(100);

}

つまり、use strictモードでなければ、argumentsオブジェクトは書き換えられます。

function myFunction3_23_04() {

  /**
   * 引数を操作する関数
  */
  const getArgument = function (parameter) {
    parameter = 200;

    console.log(arguments); //{ '0': 200 }
    console.log(parameter); //200

    console.log(arguments[0] === parameter); //true
    console.log(arguments['0'] === parameter); //true
  };

  getArgument(100);

}

また、use strictモードは、残余引数がある関数内に記述できません。

function myFunction3_23_05() {

  /**
   * 引数を操作する関数
  */
  const getArgument = (...parameter) => {
     // 'use strict'
     // SyntaxError: Illegal 'use strict' directive in function with non-simple parameter list
  };

  getArgument(100, 0);

}

前者は7の補足ということにしましょう。後者は、strictモード挙動リストに追記します。

strictモードで効く主な厳格

  1. 暗黙的なグローバル変数の禁止
  2. 代入不可なプロパティへの代入の禁止
  3. 削除できないプロパティの削除の禁止
  4. 関数の引数名の重複の禁止
  5. 幾つかの識別子は予約語にするため使用禁止(staticとか)
  6. 8進数表記の禁止
  7. eval 変数、arguments 変数の宣言禁止
  8. with 禁止
  9. ブロックスコープ内の関数定義
  10. 残余引数をもつ関数内へのuse strictの記述禁止  ← New

argumentsオブジェクトのコピー

テキストでは、argumentsオブジェクトのコピーを作成してから変更を加えましょう、というテクニックを紹介していましたが、残余引数を使うことで、複製を作成することになります。

use strictモードを使わなくてもこのように回避できるでしょう。

function myFunction3_23_06() {

  /**
   * 引数を操作する関数
  */
  const getArgument = function (...parameter) {
    parameter = 200;

    console.log(arguments); //{ '0': 100, '1': 0 }
    console.log(parameter); //200

    console.log(arguments[0] === parameter); //false
    console.log(arguments['0'] === parameter); //false
  };

  getArgument(100,0);

}

まとめ

以上で、「argumentsオブジェクトを書き換えない」をお届けしました。

use strictモードとスプレッド構文が大活躍でした。

callメソッドが、対象のオブジェクトと引数が普段と逆なのがどうも苦手です!

次回は、「argumentsへのリファレンスは変数に保存する」 をお届けします。

参考資料

arguments MDN

このシリーズの目次

タイトルとURLをコピーしました