Edited at

【JavaScript 再入門】 基本構文編


前置き

今月で JavaScript 歴 1 年になりました。

Node.JS、バニラ js、React を使ってきました。

(JavaScript 以外にも、C#、Ruby、Swift とか少しずつ色々してます。)

その結果、「ソースを読めば何をしたいか理解できるようになってきた」

...そう思ってた時期が自分にもありました。

OSS のソースを読む機会があり、

その時、prototypeがいきなり現れ、、、ナニソレオイシイノ状態に、、、

ということで改めて JavaScript を基礎から勉強しよう、と思い本記事を書くに至りました。


ECMAScript


説明

ECMAScript は JavaScript の標準仕様書であり、この ECMAScript をもとに JavaScript が作られています。

ECMAScript は毎年バージョンアップされ、その都度、JavaScript の言語仕様が変わっています。

ES6 だの ES7 だの聞くかと思いますが、基本的には

ECMAScript2015(2015年バージョン) と ES6

ECMAScript2016(2016年バージョン) と ES7

はそれぞれ同意語のようです。

この ECMAScript ですが、ES6(つまり ECMAScript2015)で大きく変わりました。

const, let, 分割代入, class などなど。

今まで、JavaScript には無かった機能が一気に投入され、書き方が大きく変わりました。

本記事では両方と比較しながらまとめていきます。


変数の宣言 var, let, const

ソース
スコープ
特徴

(無)
word = "HelloWorld"
常にグローバルスコープ
同名変数があった場合は上書き
use strictを使用した際はエラーが発生する

var
var word = "HelloWorld"
グローバルスコープ / 関数スコープ
重複する変数が一つのスコープ内にあった場合、上書きされる

let
【ES6】
let word = "HelloWorld"
グローバルスコープ / 関数スコープ / ブロックスコープ
重複する変数が一つのスコープ内にあった場合、エラーが発生する

const
【ES6】
const word = "HelloWorld"
グローバルスコープ / 関数スコープ / ブロックスコープ

letの特徴に加え、定数である
プリミティブ型は書き換え不可
参照型の内部の値は書き換え可


スコープ

JavaScript の変数のスコープは以下の 3 つです

種類
説明

グローバルスコープ
スクリプト全体から参照できる

ローカルスコープ
関数の中からのみ参照できる

ブロックスコープ
ブロックの中からのみ参照できる

ES6 で登場した、let,constを使用することでブロックスコープを定義することができます。

ブロックスコープを使用しないということは下記のようなコードがかけます。

if (true) {

var hello = "Hello World"
console.log(hello) // Hello World
}
console.log(hello) // Hello World

予期せぬ動作を回避するために

ES6 で書ける環境ではvarではなく、ブロックスコープを持つletconstを使用することが推奨されています


余談

※Swift 等のletvarとは全く意味が違うので注意!

var はバグの温床になるため、ES6 以上が使える場合は積極的に let,const を使うのが一般的なようです。

私はたまに swift でletで宣言したけど、書き換えできなかった

とかなるので。。。


JavaScript のデータ型

JavaScript は動的型付け言語のため、Java や C#のように変数宣言時にデータ型が決まりませんが、型は存在します。


一覧

種類
データ型
意味

プリミティブ型
number
数値を表す型

プリミティブ型
string
文字列を表す型

プリミティブ型
boolean
真偽値(true / false)を表す

プリミティブ型
symbol
シンボル?を表す (次回?まとめます。。。)

プリミティブ型
null
オブジェクトが存在しないことを表す型

プリミティブ型
undefined
値が未定義であることを指す型
例)未代入の変数、戻り値が未定義の関数の戻り値

参照型
Object
上記以外


補足 プリミティブ型

プリミティブ型はメソッドを持たないデータ型のことです。

ですが、JavaScript では以下のようにかけます

const hello = "javascript";

const uppperHello = hello.toUpperCase();
console.log(uppperHello); // JAVASCRIPT

これは、JavaScript が string 型(プリミティブ型)から string のラッパーオブジェクトである String オブジェクトに自動変換してくれているため、実行できます。

(new String(hello)).toUpperCase()


【ES6】文字列へ変数を埋め込む \${expression}

let name = "matsuda"

console.log(`彼は${name}です。`) // 彼はmatsudaです。
console.log(`彼は${20 + 4}歳です。`) // 彼は24歳です。

バッククォート「``」と「\$」を使用することで文字列リテラルの中で変数や式を使用することができます。

MDN テンプレート文字列


【ES6】分割代入 { user_id, user_name, ... } = { user_id:"0001", user_name: matsuda, user_old: 24 }

分割代入とは、配列 / オブジェクト から値を取り出し個別の変数に代入し直す JavaScript の構文のことです。


オブジェクト

const userInfo = {

name: "matsuda-naoya",
old: "24",
birthplace: {
country: "Japan",
prefecture: "ehime"
}
};

// --- ES5まで ---
// const name = userInfo.name;
// const prefecture = userInfo.birthplace.prefecture;
// const likeProgrammingLanguage = "JavaScript";
// const another = { old : userInfo.old}

// --- ES6から ---
const {
name: userName, // 1 変数userNameにuserInfo.nameを代入
birthplace: { prefecture }, // 2 変数prefectureにuserInfo.birthplace.prefectureを代入
likeProgrammingLanguage = "JavaScript", // 3 変数likeProgrammingLanguageに"JavaScript"を代入
...another // 4 変数anotherに{old: "24"}オブジェクトを代入
} = userInfo;

console.log(userName); // matsuda-naoya
console.log(prefecture); // ehime
console.log(likeProgrammingLanguage); // JavaScript
console.log(another) // { old: "24"}
};



  1. 変数名: 別名と記載することで分割代入時に変数名を変更できる


  2. 変数名: { 入れ子の変数名 }と記載することで入れ子のオブジェクトも個別に展開することができる


  3. 変数名 = リテラルとすることで、分割対象のプロパティが存在しなかった場合、指定したリテラルで初期化する


  4. ...変数名とすることで分割代入によって展開されなかった残りの列挙可能なプロパティを指定した変数に代入する


配列

const snsList = ["line", "twitter", "youtube", "facebook", "Instagram"];

// ES5まで
// const LINECorporation = snsList[0]
// const twitter = snsList[1]
// const faceBookInc = [snsList[3], snsList[4]]

// ES6から
const [
LINECorporation, // 1. 変数LINECorporationにsnsList[0]を代入
twitter, // 1. 変数twitterにsnsList[1]を代入
,   // 2. snsList[3]の値は無視する
...faceBookInc // 3. snsListの残りの値をfaceBookIncに代入
] = snsList;
console.log(LINECorporation); // line
console.log(twitter); // twitter
console.log(faceBookInc); // ["facebook", "Instagram"]



  1. [変数名, 変数名] = 配列と記載することで配列の Index 順に、宣言した変数に代入される


  2. , ,と記載することでそのインデックスに応じた値は代入されない(無視される)


  3. ...変数名とすることで分割代入によって展開されなかった残りの値が指定した変数に代入される

MDN 分割代入


false になる値(falsy)

以下は Boolean 型に変換された際に false になる値です。


  • "", ``, '' (空文字)

  • 0 (数値型のゼロ)

  • NaN (Not a Number)

  • null

  • undefined

上記以外はtrueになります

JavaScript は動的型付けで、if(hogehoge)のように記載した場合は強制的に型変換が行われるため、以下のようなコードがかけます。

if("") {

// 実行されない
}
if(0) {
// 実行されない
}
let emptyName;
if (emptyName) {
// 実行されない
}

const name = "matsuda";
if (name) {
console.log(name) // matsuda
}

MDN Falsy


論理演算子 ( && || ) とショートサーキット評価(短絡演算子)

JavaScript には以下の 3 つの論理演算子が存在します。

演算子

説明

&& (AND)
value1 && value2
value1 が false とみなせる場合、value1 を返し、
true とみなせる場合は value2 の値を返す
すなわち、左右どちらも true の場合 true を返し、
左が false の場合 false を返す

|| (OR)
value1 || value2
value1 が true とみなせる場合、value2 を返し、
false とみなせる場合は value1 の値を返す
すなわち、左右どちらも true の場合 true を返し、
左が false の場合、右の true を返す

! (NOT)
!value
式が true とみなせる場合は false を返し、false とみなせる場合は true を返す


ショートサーキット評価

論理演算子&&||は左の式から右の式順で評価が行われ、左側の式を評価した際に最終評価が確定した場合は、右側の式は評価されません。

さらに、&&||は Boolean 型以外も返却できるため、以下のような書き方ができます。

  let emptyName;

emptyName = emptyName || "初期値" // 1
console.log(emptyName) // 初期値

let tempObj = {
notEmpty: "空じゃないよ"
};
temp = tempObj && tempObj.notEmpty // 2
console.log(temp) // 空じゃないよ


  1. emptyName はundefinedfalseとみなすことができ、||の性質から、右辺の初期値emptyNameに代入される

  2. tempObj は falsy な値でないため、trueとみなすことができ、&&の性質から、右側の値がtempに代入される
    ※ 2 の書き方は直感的に理解しにくいため、三項演算子を使用した書き方や、デフォルト引数【ES6】で書く場合が多いとか...
    (この辺は関数編で詳細にまとめます...)

// 三項演算子

temp = tempObj ? tempObj.notEmpty : ""

// 【ES6】デフォルト引数
function main(firstName, familyName = "Matsuda") {
return firstName + familyName;
}
console.log(main("Naoya")); // NaoyaMatsuda


オブジェクトの null チェック

!演算子を使用することで、以下の書き方ができます。

let notEmptyObj = {

name: "matsuda"
}
if (notEmptyObj) {
// notEmptyObjに値がある場合(falsyな値でない)場合処理が実行
}

let emptyObj = undefined
if (!emptyObj) {
// emptyObjがundefined(falsyな値の)場合処理が実行
}


まとめ

JavaScript の基本構文についてまとめました。

冒頭のprototypeはどこじゃいってなりそうですが、スミマセン。

いざ再学習し始めると想像以上に知らなかったことや詳細を理解していないことがたくさんあり、予想以上に時間がかかってしまいました。

関数やオブジェクトについては次回まとめることにします。


追記

まとめました!

【JavaScript 再入門】 オブジェクトの初期化と列挙編


参考

改訂新版 JavaScript 本格入門~モダンスタイルによる基礎から現場での応用まで

JavaScript の「&&」「||」について盛大に勘違いをしていた件

[WIP]JavaScript の入門書

MDN web docs