どうも。つじけ(tsujikenzo)です。このシリーズでは2021年8月からスタートしました「ノンプロ研EffectiveJavaScript輪読会」についてお送りします。
前回のおさらい
前回は、「可変長引数関数を作るには、argumentsを使う」をお届けしました。
今回は、「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モードで効く主な厳格
- 暗黙的なグローバル変数の禁止
- 代入不可なプロパティへの代入の禁止
- 削除できないプロパティの削除の禁止
- 関数の引数名の重複の禁止
- 幾つかの識別子は予約語にするため使用禁止(staticとか)
- 8進数表記の禁止
- eval 変数、arguments 変数の宣言禁止
- with 禁止
- ブロックスコープ内の関数定義
- 残余引数をもつ関数内への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へのリファレンスは変数に保存する」 をお届けします。
参考資料
このシリーズの目次
- [EffectiveJavaScript輪読会3]関数、メソッド、コンストラクタの、呼び出しの違いを理解する
- [EffectiveJavaScript輪読会3]高階関数を快適に使えるようにしよう
- [EffectiveJavaScript輪読会3]カスタムレシーバ付きでメソッドを呼び出すにはcallを使おう
- [EffectiveJavaScript輪読会3]いくつでも引数をとれる関数を呼び出すにはapplyを使おう
- [EffectiveJavaScript輪読会3]可変長引数関数を作るには、argumentsを使う
- [EffectiveJavaScript輪読会3]argumentsオブジェクトを書き換えない
- [EffectiveJavaScript輪読会3]argumentsへのリファレンスは変数に保存する