😎

JavaScript入門(基本文法)

2023/01/16に公開

プログラムの基本構造

JSに限らず全てのプログラムは以下の3つのみで構成されている

  1. 順次進行(上から順に実行)
  2. 条件分岐
  3. 繰り返し処理

環境構築

以下のものを用意する

  • VScode(コードを書くためのエディタ)
  • Node.js(ローカル上でJSを実行させるためのツール)

実行準備

  • Desktop上にstart_jsフォルダを作成して、VScodeを開く
% cd Desktop
% mkdir start_js
% cd start_js 
% code .
  • start_js/Greeting.jsを作成

実行(ターミナルに出力)

  • まずは、ファイルに以下を記述し、save
Greeting.js
console.log("Good morning");
console.log("Good afternoon");
console.log("Good evening");
  • VScode上でターミナルを開く
  • node ファイル名で実行(ここでは、「node Greeting.js」
  • ターミナルに出力されていることを確認

変数

  • 1変数につき、1つの値を代入することができる
  • 変数を定義することを「変数の宣言」と呼ぶ
  • var, let, constを変数の前につける
    • 値の再代入が不要な場合はconst(関数、クラス定義など)
    • そうでない場合はlet
    • varは使わない
//変数を宣言した後に値を代入し、タミーナルに出力
var num;
num = 1;
console.log(num);

//変数の宣言と値の代入を同時に行い、ターミナルに出力(一般的な方法)
var num = 2;
console.log(num);

変数名のルール

  • エラーが起こる場合

    • 数字が先頭から始まる変数名
    • _や$マーク以外の記号を含んだ変数名
    • 予約語(for, whileなど)と同じ変数名
  • 大文字小文字の変数名は別物扱いされる

データ型

  • JSは、動的型付け言語(pythonなどと同じ)
    • そのため、変数にデータを代入する時にデータ型を指定する必要がない
  • TypeScriptは、静的型付言語
    データ型を確認する関数typeof()
var num01 = 123;
console.log(num01);
console.log(typeof(num01));
  • データ型
    • 文字列:string
    • 数値:number
    • ブーリアン:boolean

※JSでは、他の言語と異なり小数点などは全てnumber型に統一されている

配列

  • 変数とは異なり、複数の値を代入することができる
  • 0からインデックスがスタート

配列のデータ型を調べる方法

  • 上記と同様にtypeof()を使っても配列のデータ型を調べることができない。
    • 理由:配列とオブジェクト(辞書)どちらに対してもobjectを返すので、どっちかがわからないから
  • Array.isArray()を使うことで配列の場合は、trueを返す
console.log(typeof(arr));  //わからない
console.log(Array.isArray(arr)); //これを使う

配列の作り方

  • 配列の作り方は以下の2通り
    • Array()で作成
    • []で作成(一般的)

Array()で作る

  • ①空の配列を作る場合
    • Arrayに配列の要素数を指定して、からの配列を作る。その配列にデータを代入していく。
    • arr[3] = "test"としてもエラーにならない。出力結果→[ 'apple', 'lemon', 'banana', 'test' ]
var arr = new Array(3);

arr[0] = "apple";
arr[1] = "lemon";
arr[2] = "banana";

console.log(arr);
  • ②データ込みの配列を作成する場合
    • 直接データを指定して、それをもとに配列を作成する。。
    • console.log(arr[0]);のようにして、要素を出力する
var arr = new Array("apple", "lemon", "banana");

console.log(arr);

[]で作る

  • ①空の配列を作る場合
    • []でからの配列を作ってから、データを代入していく
var arr = [];

arr[0] = "apple";
arr[1] = "lemon";
arr[2] = "banana";

console.log(arr);
  • ②データ込みの配列を作成する場合
var arr = ["apple", "lemon", "banana"];
console.log(arr);

演算子

算術演算子

var x = 10;
var y = 3;

console.log(x + y); //13
console.log(x - y); //7
console.log(x * y); //30
console.log(x / y); //割り算 3.3333333333333335
console.log(x % y); //剰余 1

比較演算子

var x = 10;
var y = 3;
var z = 10;

console.log(x > y); //true
console.log(x < y); //false
console.log(x >= y); //true
console.log(x == z); //ture
console.log(x != y); //true

論理演算子

  • bool型に用いる演算子
  • かつ→&&
  • または→||
var x = 10;
var y = 3;

console.log(x >= 5 && y == 3); //true
console.log(x == 5 || y == 3);  //true

「または」の場合:一つでもtrueがあればtrue
「または」の場合:全てtrueであればtrue

代入演算子

これまで、代入に使ってきた=の事

複合代入演算子

算術演算子と代入演算子を組み合わせたもの

var x = 10;
var y = 3;

x += y; //x = x + y;と同じ
y -= 3; //y = y - 3;と同じ

console.log(x); //13
console.log(y); //0

インクリメントとデクリメント(前置) ※これを使うことが一般的

  • すぐに計算結果を変数で格納できる++xには、xに1を足したデータを格納する。
  • インクリメント:++変数名変数の値に1を足す
  • デクリメント:--変数名変数の値に1を引く
前置の場合
var x = 10;
var y = 3;

console.log(++x); //インクリメント 11
console.log(--y); //デクリメント 2
  • 後置のインクリメント、デクリメントではx++には元のxを格納。再度x表示することで1足し算される。
後置の場合
var x = 10;

console.log(x++); //x++では現在の値を格納している 10
console.log(x); //xでは、X++によって足し算された結果が格納される 11

条件分岐

if文

  • if (条件) {条件を満たした場合の処理;}
  • 条件がfalseの場合は、{}内の処理を実行しないbreak
var age = 22;

if (age >= 20) {
    console.log("大人");
}
// 出力結果:大人

if~else文

  • if(条件){条件を満たした場合の処理;}else{条件を満たさなかった場合の処理;}
var age = 17;

if (age >= 20) {
    console.log("大人");
} else{
    console.log("子供");
}
// 出力結果:子供

if~else if文

  • if(条件A){条件Aを満たした場合の処理;} else if(条件B){条件Bを満たした場合の処理;} else{条件を満たさなかった場合の処理;}
var age = 0;

if (age >= 20) {
    console.log("大人");
} else if (age == 0) {
    console.log("赤ちゃん");
} else{
    console.log("子供");
}
// 出力結果:赤ちゃん
  • pythonのように「20 > age >= 10」とはできない
応用
var age = 10;

if (20 > age && age >=10) {
    console.log("10代");
} else if (30 > age && age >= 20) {
    console.log("20代");
} else if (40 > age && age >=30) {
    console.log("30代");
} else {
    console.log("それ以外");
}

繰り返し処理

  • Reactでは、使用しないので学習をスキップ
    • 理由:Reactなどのアプリ開発では、フロントをJSXで記述する場合がほとんど。JSX内ではJSのfor文が使用できない。そのため、代わりにmap()関数が使用されるため。

関数

  • 関数を作ることを「関数を定義する」と呼ぶ
  • 関数の定義方法は主に以下の3つ
    • 関数宣言(基本)
    • 関数式(無名関数とアロー関数) ※アロー関数が一般的

①基本的な関数

  • 関数の定義:function 関数名(引数名) {実行したい処理;};
  • 関数の呼び出し:関数名();
function hello() {
    console.log("hello world");
};

hello(); //hello world
function sum (x, y) {
    return x + y;
};
let result = sum(1, 3);
console.log(result); //4

②式による関数定義(アロー関数がほとんど用いられる)

  • 式による関数定義とは、関数を変数に代入したもの
  • 無名関数を用いる場合、アロー関数を用いる場合に分けられる(アロー関数の方が楽)

無名関数

  • 関数定義:var 変数名 = function (引数){実行したい処理;};
  • 関数の呼び出し:変数名();
let Hey = function () {
    console.log("hello world");
};
Hey(); //hello world
let sum2 = function (x, y) {
    return x + y;
};
console.log(sum2(1, 3)); //4

アロー関数(一般的)

  • 変数に代入して、式として関数を定義する
  • 名前の通り矢印の=>を用いて関数を定義する。functionの代替。
  • 関数定義:(引数) => {実行したい処理};
  • 関数の呼び出し:変数名();
let Hey = () => {
    console.log("hello world");
};
Hey(); //hello world
let sum2 = (x, y) => {
    return x + y;
};
console.log(sum2(1, 3)); //4

クラス

  • プロパティ:クラス内で定義された変数(pythonでいう属性。呼び方の違い)
  • メソッド:クラス内で定義された関数

プロパティと変数、メソッドと関数の違い

  • クラスの中で定義したかどうか
  • クラス内で定義した変数のことを「プロパティ」
  • クラス内で定義した関数のことを「メソッド」

クラスの定義

  • クラスの定義方法は主に以下の2つ
    • クラス宣言(基本)
    • クラス式

①クラス宣言

  • クラス宣言:class クラス名 {}
  • インスタンス作成let 変数名 = new クラス名();

メソッドの定義

// jsではクラスの頭文字を大文字にする
class Student {
    // メソッドはfunctionの記述が不要
    avg(math, english) {
        console.log((math + english) / 2);
    }
}

//インスタンスを作成することでクラスを使用できる
//student1インスタンス
let student1 = new Student();
student1.avg(80, 70);

//出力結果:75

プロパティの追加

プロパティを後から定義(追加)
let student1 = new Student();

student1.name = "takesi"; //後からプロパティを追加

console.log(student1.name); //出力結果:takesi

しかし、これだと作成するインスタンス全てにプロパティを追加する記述をしなければならない
これを防ぐためにコンストラクタを定義する

コンストラクタの定義(≒プロパティの定義)

  • インスタンスが作成された時に、自動で実行するメソッド(初期化メソッドとも呼ばれる)
  • これにプロパティを定義しておけば、インスタンスごとに自動でプロパティが作成される。
  • コンストラクタの定義:constructor (引数) {実行する処理};
// jsではクラスの頭文字を大文字にする
class Student {
    constructor (name) {
        this.name = name; //thisにインスタンスが代入される
    }
}

//インスタンスを作成することでクラスを使用できる
//student1インスタンス
let student1 = new Student("takesi");
console.log(student1.name); //出力結果:takesi

//student2インスタンス
let student2 = new Student("nobita");
console.log(student2.name); //出力結果:nobita

②クラス式

  • 変数にクラスを代入するものなので、クラス名を省略可
  • let Student = class{};
// クラスを変数に代入しただけ
let Student = class {
    constructor (name, math, english) {
        this.name = name; 
        this.math = math;
        this.english = english;
    }
};

let student1 = new Student("takesi");
console.log(student1.name);

let student2 = new Student("nobita");
console.log(student2.name);

※ただクラス名を省略して、変数に代入しただけ

クラスの応用

プロパティをメソッドで用いる場合

  • メソッド側で、this.変数名でプロパティを受け取る
  • その際、メソッドに引数は不要
class Student {
    constructor (name, math, english) {
        this.name = name;
        this.math = math;
        this.english = english;
    }
    avg() {
        const result = (this.math + this.english) / 2;
        return result;
    }
}

let student1 = new Student("takesi", 80, 70);
console.log(student1.name);
console.log(student1.avg());

プロパティとメソッドを切り離す場合(クラスで処理をまとめたい時)

  • 以下のコードの場合は、クラスと関数で分離した方がいい
  • クラスで処理をまとめたい場合に、以下のように記述できる
  • 以下のコードのように、上のコードをプロパティで配列を受け取るようにするといい
class Student {
    constructor (name, math) {
        this.name = name;
    }
    avg(scores) {
        let num = 0;
        const sum = scores.map((score)=>{
            num += score;
        })
        const result = num / scores.length;
        return result;
    }
}

let student1 = new Student("takesi");
console.log(student1.name);

const score = [70, 70, 70];
console.log(student1.avg(score));

その他の要点

①変数宣言のキーワード

  • JavaScriptでは、「これは変数です」と変数を宣言するためのキーワードが以下の3つある。
    • var, let, const
    • varは使わない(再宣言、再代入、スコープの問題から)
再宣言、再代入の違い const let var
変数の再宣言 × ×
変数の再代入 ×

- スコープ:データを参照できる範囲のこと
- 変数を宣言した場所によって、その変数が持つスコープ(作成されるスコープ)が異なる
- 所持(作成)できるスコープは、変数を宣言する予約語(const, let, var)によって異なる

作成されるスコープの違い const let var 関数の仮引数
グローバルスコープ
関数スコープ
ブロックスコープ × ×
  • グローバルスコープ:トップレベル(=シンプルなブロックの外での宣言のこと)で変数宣言をした際、その変数はグローバルスコープを持つ
  • 関数スコープ:関数のブロック内で変数宣言した際、その変数は関数スコープを持つ
  • ブロックスコープ:ブロック内で変数宣言した際、その変数はブロックスコープを持つ

※グローバルスコープを持った変数は、どこからでも参照することができる
※関数、ブロックスコープを持った変数は、そのブロック内でしか参照することができない

つまり、ブロック内にvarを使って変数を宣言した場合でもブロック外からその変数を参照できてしまう。(varではブロックスコープが作成されないため)

②ブロック

  • ブロック:{}で囲まれたコード。for文などで用いられるが、以下のように単独でも使用できる
  • ブロック文は0個以上の文をグループ化したい時に使用する(divてきな)
  • スコープの理解に必要な知識

const, letによりブロック内で、宣言された変数はブロックスコープを持つ。
つまり、ブロック内と外とでは、同じ変数名でも異なるものとして扱われる。

let test = 10;

{
    let test = 1;
    console.log(test); //出力結果:1
};

console.log(test); //出力結果:10

varによりブロック内で、宣言された変数はブロックスコープを持たない。
つまり、ブロック内と外に関係なく同じ変数として扱われる。

varの場合は注意
var test1 = "apple"
{
    var test2 = "banana";
};
console.log(test1);
console.log(test2);

スコープ

  • グローバルスコープ
  • ローカルスコープ(関数スコープ、ブロックスコープ)

グローバルスコープ

  • グローバルスコープ
  • トップレベルで宣言された変数(グローバル変数)に与えられるスコープの事
  • トップレベルとはブロックの外、つまり、シンプルにファイルに書き込むという事
  • ブロック、関数内でも参照することができる
  • var, let, constの全ての予約語で取得することができる
var scope = "globalスコープ"; //グローバルスコープ

console.log(scope); //出力結果:globalスコープ

const scopeFunc = () => {
    console.log(scope); //関数内でもscope変数を参照できる
};
scopeFunc(); //出力結果:globalスコープ

// 出力結果:
//globalスコープ
//globalスコープ

ローカルスコープ

  • ローカルスコープ
    • 関数スコープ
    • ブロックスコープ

関数スコープ

  • 関数内で宣言した変数に与えられるスコープ
  • つまり、関数A内で宣言した変数は、関数A以外では参照できない(エラーになる)
  • var, let, constに関係なく、全ての変数に与えられる
const scopeFunc = () => {
    const scope = "funcスコープ"
    console.log(scope);
};
scopeFunc(); //出力結果:funcスコープ

console.log(scope); //出力結果:ReferenceError

ブロックスコープ

  • ブロック内で宣言した変数に与えられるスコープ
  • つまり、ブロックA内で宣言した変数は、ブロックA以外では参照できない(エラーになる)
  • let, constの変数に与えられる
const scope = "globalスコープ";

{
    const scope = "blockAスコープ"
    console.log(scope); //出力結果:blockAスコープ
};

{
    const scope = "blockBスコープ"
    console.log(scope); //出力結果:blockBスコープ
};

console.log(scope); //出力結果:globalスコープ

// 出力結果:
//blockAスコープ
//blockBスコープ
//globalスコープ

④constの再代入エラーの意味(注意点)

  • constの再代入禁止の意味(=変数名の上書きはエラーという意味)
  • 変数名の更新はエラー
  • つまり、変数の更新はダメで、オブジェクト自体の更新は可能
const test1 = ["apple", "lemon", "banana"];

test1[0] = ""; //変数の再代入ではない(配列オブジェクトの中身の更新)

console.log(test1);  //出力結果:['', 'lemon', 'banana']

test1 = [1]; //エラー(変数を上書きしているのでエラー)

Discussion