JavaScript本格入門を読んで、初心者がつまづいたポイントまとめ


この記事は改訂新版JavaScript本格入門 ~モダンスタイルによる基礎から現場での応用までの読書メモです。

初心者的観点からJavaScriptでつまづいたポイントなど備忘録として書き留めておきます。本記事の主な内容は以下の通りです。

・関数宣言
・引数の使い方とスコープ
・ES2015で追加された仕様

■関数宣言(命令)の方法

1.function命令で宣言

function doSomething() {
  //任意の処理
  return something;
}

一番オーソドックスな書き方ですね。returnはなくても良いらしい。
引数はなくても良いけど()は省略不可。()自体が「関数を使います」と宣言するものとして覚えておくと良いらしい。

2.関数リテラル

無名関数を変数に宣言格納する方法。

var doSomething = function(a,b) {
  return a * b;
}

3.アロー関数

関数リテラルの書き方をよりシンプルにしたもの。

let doSomething = (a,b) => {
  return a * b;
}

■つまづきポイント

1.function命令はコードを解析・コンパイルする時点で関数登録をしている

以下は、function命令が関数呼び出しより後に書かれているが正しく使用できる。

console.log(addNum(2,8)); //10
function addNum(a,b) {
  return a + b;
}

以下の書き方(関数リテラル)は上記と同じように使うと実行時エラーになる。

console.log(addNum(2,8)); //エラー
var addNum = function(a,b) {
  return a + b;
}

関数リテラル(とFunctionコンストラクタ)は実行時(代入時)に評価されると覚えておく。普通の変数と同じ。
function命令は静的な構造を宣言するキーワードであるため、コードを解析(コンパイル)する際に関数が登録され、ソースのどの場所から呼び出されても使用可能となっている。

2.スコープ

・ES2015以前はブロックレベルのスコープが存在しない。

if(true) {
  var name = '鈴木';
}
console.log(name);//鈴木

上記と同じことをJavaで行うとエラーになる。
JavaScriptはブロックレベルのスコープが存在せず、ブロックを抜けた後でも変数iは有効。
しかしこれは変数の競合を生んでしまう原因にもなるため、ES2015からはブロックスコープに対応している。

・ブロックスコープに対応したlet命令

if(true) {
  let name = '鈴木';
}
console.log(name);//エラー

今は上記の書き方が主流のよう。

3.引数の数をチェックしない

function addNum(a,b) {
  console.log(a + b);
}
console.log(addNum(2,8));//10
console.log(addNum(2,8,3));//10
console.log(addNum());//NaN(Not a number)

左から順に引数を受け取り、使用されていない引数は無視される。
与えられた引数の数は関数側でチェックしない。
argumentsオブジェクトに引数が格納されるため、それを利用してチェックすることができる。

var addNum = function(a,b) {
  if(arguments.length !== 2){
    throw new Error('引数の個数が違います');
  }
  console.log(a + b);
}

try{
  addNum(1);
}catch(e) {
  window.alert(e.message);//エラーダイアログ表示
}

■ES2015で追加された仕様

1.可変引数の定義

仮引数の前に「...」をつける。
ループで引数を動的に操作する際に使えそうです。

function sum(...nums) {
  let result = 0;
  for(let num of nums) {//拡張for文
    result += num;
  }
  return result;
}

可変引数を受け取る関数であることを明示的に表しているためわかりやすい。また、全ての配列オブジェクトを受け取れる。

2.名前付き引数コード

仮引数を {プロパティ = デフォルト値,...} の形式で宣言することで、関数内では順番に評価するのではなく個別の引数として扱える。

function calcAvr({math = 80,english = 90, japanese = 70}){
  return (math + english + japanese)/3;
}
console.log(calcAvr({math70,english80,japanese90}));

また、下記のようにオブジェクトから特定のプロパティを取得することも可能。

let user = {
  uid: 'u001',
  name: '鈴木',
  team: 'A'
}

function userNm({name}) {
  console.log(name);
}

userNm(user);//鈴木

■さいごに

JavaScriptはこれまで業務で使う中では付け焼き刃的に対処してきたので、ちゃんと基礎固めしたいと思い、冒頭で述べた本を使って勉強中です。
また残しておきたいトピックがあれば更新します!