JavaScriptまとめ

はじめに

TypeScriptを学ぶ前にJavaScriptに関して改めて基礎的な部分を学習しなおしました。

この記事では、個人的に理解が浅かった部分をまとめています。

✅ゴール

・JavaScriptの理解を深める

✅参考教材

📚改訂新版JavaScript本格入門 ~モダンスタイルによる基礎から現場での応用まで ES6基準の書籍
※以降、本格入門

📚パーフェクトJavaScript
※以降、PFJS

👇こっちに少し移しました。

プログラミング用語と言語まとめ

特徴

①スクリプト言語

簡易なプログラミング言語。CやJavaに構文が似ている。

②動的型言語

データ型について寛容でJavaやCと異なる(JavaやCは返り値に型の指定がある)。

③インタプリンタ言語

コンピューターに理解できる形式に翻訳しながら実行していく言語⇔コンパイル言語に比べ実行速度が遅い。

④プロトタイプベースのオブジェクト指向

クラスベースのオブジェクト指向とは少し違う。

※オブジェクト指向とは、オブジェクトを中心としてコードを組み立てていく手法。オブジェクトはプロパティとメソッドから構成される。

⑤関数型プログラミング

手続き型プログラミング(※オブジェクト指向もその一種)をサポートしているが、関数をオブジェクトで扱える点と関数リテラルがあることで関数型プログラミングをサポートできる。

知っておいたほうが良いこと

🙄手軽にJavaScript単体の動作を確認するのであればJSFiddleがおすすめです。もしくはVScode。

※ES6を使いたい場合は以下記事参考。

VSCodeでNode.js+Babelを使ってJavaScript(ES6)を実行する

✅ECMAScript 2015(通称ES6)

・class命令の導入(※プロトタイプ。少し縛りが弱いクラスのようなもの。)
※Functionオブジェクトで表現していたクラス(コンストラクター)をわかりやすく表現したものにしかすぎない
・import/export命令によるコードのモジュール化対応
・アロー関数の導入など

👉ES6未対応のブラウザに対応するため、トランスコンパイラーとしてBABELを使い、ES5仕様に変更すること多々。

✅記述ルール

・文末にセミコロン(;)を付ける
・大文字/小文字が区別される
・変数varは省略可能。この場合グローバル変数となる。が、非推奨。
・定数はすべて大文字にする慣習がある。

✅<script>要素を記述する場所

HTML上では</body>閉じタグの直前に置く。関数定義など先に呼び出す必要のあるコードのみ、<head>要素の配下に記述する。

✅Strictモード:JSの落とし穴を検出して、エラーとして通知してくれる仕組み

※ES6に準拠していないプログラムだと、エラー検出機能など一部動作しない可能性があるため。

'use strict';

👉例えばvarの省略をすると、use strict(strict mode)ではエラーが出る。

基本

✅変数

変数の役割は値の格納やオブジェクトを名前で呼ぶこと。
※JavaScriptの変数はプロパティそのもの。

var a = a || 7;
console.log(a); // 7
a = 9;
console.log(a); // 9

-上記の変数をletで宣言するとエラーになる。
-2語以上の場合はaddNumberと大文字で区切る。
-更新するときはvar/let宣言は不要

・定数

後から値を更新できない。

const name = "sato";

・インスタンス変数(※インスタンスが格納された変数)からプロパティ/メソッドの呼び出し

var 変数名 = new オブジェクト(コンストラクター)名([引数,...])
変数名.プロパティ名[= 設定値];
変数名.メソッド名([引数[,...]]);

※組み込みオブジェクトなどインスタンスを生成せずに利用できるものを静的プロパティ/静的メソッド、クラスプロパティ、クラスメソッドと呼ぶ。

✅演算子

・文字列の連結

console.log("sato"+"takashi"); // satotakashi

・変数との連結

let name = "sato";
console.log(name + "さん"); // satoさん
let number = 11;
console.log(number + 5); // 16
console.log(`こんにちは、${name}さん`)

※ES6から連結方法にテンプレートリテラルが使える。その場合は文字列全体をバッククォーテーションで囲む。

・==/===

==は等価演算子で===は同値演算子。
同値演算子ではデータ型を変換しないので、基本こっちを使う。

let a = 1;
let b = '1';
console.log(a == b);
console.log(a === b);
//出力
true
false

new(インスタンス生成)も演算子の1つ。

・条件式||

const number = 3;
if(number > 1 || number > 10){
  console.log(number); // 3
}

 

✅リテラル

データ型に格納できる値そのもの、また、値の表現方法。
※JavaScriptに標準で組み込まれた組み込みオブジェクトに対応しており、new演算子を使って明示的にオブジェクトを作ることも可能だが原則避けること。※本格入門P113

数値リテラル(number)

小数点以下は正確に表現できないことがある。

文字列リテラル(string)

シングルクォート/ダブルクォートで囲む。

配列リテラル

データの集合。仕切りの1つ1つに格納された値を要素と呼ぶ。
[]でくくった形式で表現。配列名[インデックス番号]で個々の要素にアクセスする。

オブジェクトリテラル

各要素に文字列キーでアクセスできる配列。ハッシュ、連想配列とも呼ばれる。
※JavaScriptにおいては、連想配列とオブジェクトは同一のもの。
※配列の個々のデータは要素、オブジェクト内の個々のデータはプロパティ(関数の格納が可能)と呼ぶ。また関数が格納されたプロパティのことを特別にメソッドと呼ぶ。

・関数リテラル

関数のデータ型。JSでは関数もデータ型の一種として扱われるのが特徴。

論理(bool)リテラル

ブーリアン型は、真理値の「真 = true」と「偽 = false」という2値をとるデータ型。

・未定義値(undefined)

変数が宣言済みに関わらず、値が定義されていないことを表す値。※意図しない空を表現。

null

意図した空を表現する。該当する値がない。「空である」という状態を表す値。

✅配列

let number = [1,2,3];
console.log(number[0]); // 1
number[0] = 0;
console.log(number[0]); // 0
console.log(number.length); // 3

※配列.lengthで要素の数を出力できる。

✅オブジェクト

※すべてのオブジェクトは連想配列である。

データを操作するための様々な機能を持った入れ物。※オブジェクト=プロパティ(名前と値のペア)+メソッド

const print = console.log;

let obj = {x:3,y:4};
console.log(obj.x); // 3

let obj2 = {pos:{x:3,y:4}};
print(obj2.pos.y); // 4

obj.x = 33;
print(obj.x); // 33

obj.z = 5;
print(obj.z); // 5

print(obj); // { x: 33, y: 4, z: 5 }

※ドット演算子でプロパティにアクセスできる。また、プロパティには配列やオブジェクトの指定も可能。

配列にオブジェクト

let items = [
  {name:"sato",age:27},
  {name:"saito",age:29}
]
console.log(items[0].name) // sato

・オブジェクトの値にオブジェクト+配列

let items = [
  {
    name:"sato",
    age:27,
    favorite:{
      music:"guitar",
      sports:"basketball",
      foods:["玄米","カレー","寿司"]
    }
  },
  {name:"saito",age:29},
]
console.log(items[0].favorite.foods[0]) // 玄米

✅関数

ある一連の手続きをまとめて外部から呼び出せるようにする仕組み。functionで関数宣言する。

JS特有の特徴としては、クラスと無関係に定義できる点。JSの関数がオブジェクトである点。

function sum(a,b) {
  return a + b;
}
var a = sum(3,6);
console.log(a); // 9

※returnで関数の戻り値を取得できる。

※スコープ:関数の引数や、関数内で定義した定数や変数は、その関数の中でしか使うことができない。これはifやwhile文でも同じ(ES6のletで変更。varは該当しない)。

・関数リテラル

関数名を省略可能。

var sum2 = function(a,b) {
  return a + b;
}
var a = sum2(6,4);
console.log(a); // 10

※関数との違いはクロージャの点。

・アロー関数

「function()」の部分を「() =>」と書く

const user = {
  name:"sato",
  great:() => {
    let name = "saito";
    console.log(`こんにちは!${user.name}です`);
    console.log(`こんにちは!${name}です`);
  }
}
user.great(); 
// こんにちは!satoです
// こんにちは!saitoです

✅メソッド

オブジェクトのプロパティに関数を持たせたもの。

let obj = {};
obj.fn = function(a,b){
  return a + b ;
};
print(obj.fn(44,55)); // 99
print(obj); // { fn: [Function] }

new式/コンストラクタ

オリジナルのオブジェクトには基本手は加えず、オリジナルを複製したコピーを操作することでデータの競合を防ぐ。
そのためにnew演算子を利用してインスタンスを作る。
new オブジェクト();で宣言し、この初期化メソッドのことをコンストラクタと呼ぶ

コンストラクタはインスタンス(実体)を作成する関数のこと(普通の関数宣言と同じ)。
JSにはクラスがないので、実質コンストラクタ呼び出しを想定している関数オブジェクトをクラスと呼ぶ。
newの後に書く識別子(関数名)をクラス名とみなしても概念上の破綻はない。
new式で呼ばれたコンストラクタ内のthis参照は品気に作成するオブジェクトを参照する。

※クラスはインスタンスオブジェクトのひな型にあたるもの。

const print = console.log;
function Person(name, age) {
  this.name = name;
  this.age = age;
  this.show = function() {
    print(this.name,this.age);
  }
}

var person1 = new Person('太郎', 22);
var person2 = new Person('次郎', 31);
// 「new」を付けることで、生成されるインスタンスが「this」にセットされる

person1.show();
person2.show();
//出力結果
太郎 22
次郎 31

※参考:【JavaScript入門】コンストラクタの使い方(new/prototype/overload)JavaScriptのクラス?コンストラクタ??

👉効率が良くない、プロパティ値のアクセス制御ができない点を解決するのに、プロトタイプ継承とクロージャが必要。

✅this参照

JavaScriptのコードのどこでも使える読み込み専用の変数(関数外でも使える)。※ES5のvarが対象。

✅クラスと継承※ES6から採用

class クラス名」とすることで新しくクラスを用意できる。基本的にクラス名は大文字にする。
new演算子でインスタンスを生成する。
コンストラクタはインスタンス生成直後に実行したい処理や設定を追加する機能。クラスの中に追加。
extendsで継承し、同名のメソッドを追加した場合は子クラスが優先される(オーバーライド)。
コンストラクタをオーバーライドする際は1行目に「super()」と記述する必要がある。

class Person {
  constructor(name,age){
    this.name = name;
    this.age = age;
  }
  info(){
    this.greet(this.age);
  }
  greet(age){
    console.log(`こんにちは!${this.name}です。${age}歳です。`);
  }
}
const person = new Person("sato",27);
person.info(); // こんにちは!satoです。27歳です。
person.greet(27); // こんにちは!satoです。27歳です。
class Sato extends Person {
  constructor(name,age,food){
    super(name,age);
    this.food = food;
  }
  savingMoney(){
    return this.age * 10;
  }
  greet(age){
    console.log(`僕は今${age}歳です。好きなご飯は${this.food}です`);
  }
}
const sato = new Sato("sato",30,"カレー");
sato.info(); // 僕は今30歳です。好きなご飯はカレーです
const savings = sato.savingMoney();
console.log(savings); // 300
sato.greet(35); // 僕は今35歳です。好きなご飯はカレーです

✅分割代入

配列/オブジェクトを分解し、配下の要素/プロパティ値を個々の変数に分解するための構文。

✅型について

JavaScriptで型を持つ対象は値とオブジェクトで、変数に型はない(Javaと対照的。)。
つまり、変数に代入する値は型による制約がない。

var x = 'Hello World!!';
x = 100 // データ型が異なっていても正しく扱える。

✅Switch文

breakがないと、合致したcaseの処理を行った後、その次のcaseの処理も行ってしまう。
caseのどれとも一致しなかった場合はdefaultのブロックが実行される。

var x = 1;
switch(x){
  case 0:
    console.log(0);
  case 1:
    console.log(1);
    // break;
  case 2:
    console.log(2);
  default:
    console.log("default");
}

//出力
1      
2      
default

✅for文

for (let i = 0;i < 10;i++){
  console.log(i);
}
//出力
0
1
2
3
4
5
6
7
8
9

✅FizzBuzz(if文とwhile文)

'use strict';

function fizzbuzz(num) {
  if (num % 3 === 0 && num % 5 === 0 ){
    return "fizzbuzz";
  }else if(num % 3 === 0){
    return "fizz";
  }else if(num % 5 === 0){
    return "buzz";
  }else{
    return num;
  }
}
let num = 1;
while(num <= 10){
  console.log(fizzbuzz(num));
  num += 1;
}

※for文の場合

for (var i = 1; i <= 100; i++){
  if (i % 3 === 0 && i % 5 ===0){
   console.log("FizzBuzz");
  }else if (i % 3 === 0){
   console.log("Fizz");
  }else if (i % 5 === 0){
   console.log("Buzz");
  }else{
   console.log(i);
  }
 }

✅forin命令(連想配列の要素を順に処理する)

let data = {x:1,y:2,z:3};
for (let key in data){
  console.log(key,data[key]);
}
//出力
x 1
y 2
z 3

✅try~~catch~~finally命令:例外を処理する

try節の中で例外が発生すると実行を中断しcatch節に入る。catchかfinally片方なら省略可能。

try {
~~例外が発生するかもしれない命令~~
} catch {
~~例外が発生したときに実行~~
} finally {
~~例外有無に関わらず最終的に実行~~
}

✅標準(組み込み)オブジェクト

JavaScriptに標準で組み込まれたオブジェクトで、JSが動作するすべての環境で特別な定義や宣言なしに利用できる。

ObjectやStringなど、クラスとみなす方が理解しやすいオブジェクト多数。※PFJSではクラス、本格入門ではオブジェクトで表記されてる。

・Objectクラス(オブジェクト)

ObjectクラスはJavaScriptのすべてのクラスの基底クラス。

prototypeやconstructorもObjectクラスのプロパティになる。

・Arrayオブジェクト 参考

良く使うものの一例。

.push():配列末尾に要素を追加
.pop():配列末尾の要素を取得し、削除
.shift():配列先頭の要素を取得し、削除
.unshift():配列先頭に指定要素を追加
.splice():配列内の要素を置き換え。
.sort():要素の並び替え
.reverse():逆順に並び替え

✅グローバルオブジェクト

グローバル変数やグローバル関数を管理するために、JavaScriptが自動的に生成する便宜的なオブジェクト。
ホストオブジェクトのルートに相当するオブジェクト。this参照でアクセスできる。

※組み込みオブジェクトの一種だが特別扱い。

応用

※パーフェクトJS P110以降

✅コールバック関数

引数に入っている関数のこと。ObjectクラスやArrayオブジェクトのメソッドなどで多用する。

const numbers = [1,2,3];
numbers.forEach((number)=>{
  console.log(number);
})
//出力
1
2
3
const People = [
  {name:"sato",age:27},
  {name:"saito",age:24},
  {name:"suzuki",age:25}
]
const filteredPeople = People.filter((person)=>{
  return person.age >= 25;
});
console.log(filteredPeople);
//出力
[ { name: 'sato', age: 27 }, { name: 'suzuki', age: 25 } ]
const call = (callback) => {
  callback("sato", 27);
};
call((name, age) => {
  console.log(`${name}は${age}歳です。`);
});
//出力
satoは27歳です。

✅ファイルの分割(ES6からモジュール化に対応。)

クラスの定義の後で「export default クラス名」とすることで、そのクラスをエクスポート(出力)し、他のファイルへ渡すことができる。

class Person{
}
export default Person;

読み込む際は、「import クラス名 from “./ファイル名”」と書くことでインポートすることができる。※変数などの値も可

import Person from "./person";

※デフォルトエクスポートは1ファイル1つの値のみ使用可能。またimport時は名前に違いがあっても値が入る。

※名前付きエクスポートはdefaultを書かずに、名前を{}で囲んでエクスポートする書き方。「import { 値の名前 } from “./ファイル名”」{}で囲んで指定。複数の定数やクラスを指定してエクスポートができる。

✅変数の参照

変数は同じオブジェクトを参照する。

例)変数bが参照先オブジェクトを変更。変数aで出力しても値が変更される。

let a =  {x:1 , y:2};
let b = a.x++ ;
console.log(a.x) // 2

✅プロトタイプ

ブジェクトに対し、prototypeプロパティでプロパティやメソッドを追加することができる

※コンストラクターによるメソッド追加で起きる無駄なメモリ消費を防ぐことができる。

function MyClass(x,y){
  this.x = x;
  this.y = y;
}

MyClass.prototype.show = function() {
  console.log(this.x,this.y);
}

var obj = new MyClass(3,2)
obj.show(); // 3 2

JSではクラスという抽象的な設計図が存在せず、実体化されたオブジェクトだけ。新しいオブジェクトを生成するにも、クラスではなくオブジェクトが基になる。
この新しいオブジェクトを作るための原型を表すのがプロトタイプという特別なオブジェクト。

👉JSがプロトタイプベースの言語と言われる理由。

・全ての関数(オブジェクト)はprototypeという名前のプロパティを持つ。
・全てのオブジェクトはオブジェクト生成に使ったコンストラクタ(関数オブジェクト)のprototypeオブジェクトへの(隠し)リンクを持つ。

クラス名.prototype.メソッド名 = function(メソッド引数){メソッド本体}

②継承(基になるオブジェクトの機能を引きついて新たなクラスを作る機能)のためのプロトタイプチェーン

継承元をスーパークラス(基底クラス)、継承によってできたクラスをサブクラス(派生クラス)という。

var Animal = function() {}

Animal.prototype = {
  walk : function() {
    console.log('とことこ')
  }
};

var Dog = function () {
  Animal.call(this);
};

Dog.prototype = new Animal;
Dog.prototype.bark = function() {
  console.log('ワンワン');
}

var d = new Dog;
d.walk(); // とことこ
d.bark(); // ワンワン

※JSでは継承は動的に処理される。

✅クロージャ

一種の記憶域を提供する仕組み。

クロージャの仕組みは関数宣言の中に別の関数宣言を書けることが前提。

以下では、匿名関数がローカル変数counterを参照し続けているので、closure関数の終了後もローカル変数counterは保持され続ける。

function closure (init) {
  var counter = init ;
  return function () {
    return ++counter;
  }
}

var myClosure = closure(1);
console.log(myClosure()); // 2
console.log(myClosure()); // 3
console.log(myClosure()); // 4

※戻り値が匿名関数。引数や戻り値が関数である関数のことを高階関数という。

クライアントサイドJavaScript

✅documentオブジェクト

HTMLやCSSを操作するための機能が多数用意されている。

textContentプロパティ:取得した要素に対してテキストを埋め込む

document.getElementById('ID名').textContent = 書き換えたい文字列;

例)

<p id="choice">ここに日時を表示します</p>
<script>
  'use strict';
  document.getElementById('choice').textContent = new Date();
</script>

その他

✅ブラウザーオブジェクト

ブラウザー操作のための機能を集めたオブジェクト群の総称。

オブジェクトの例)Storageオブジェクト、XMLHttpRequestオブジェクト(Ajax※サーバー連携)、Promiseオブジェクト(※非同期処理の簡易実装。Ajaxと組み合わせることも多々。)

メソッドの例) confirmメソッド

✅非同期処理

この書籍でもasync/awaitの部分ないな~と思っていたらES8から登場したものらしい。なのでここは割愛!

JavaScriptと非同期処理の話

✅分割代入

配列またはオブジェクトから値を取り出し別個の変数に代入する。

const [a, b] = [1,2]
console.log(a) // -> 1

const { name } = { id: 1, name: 'りんご' }
console.log(name) // -> りんご

関数の定義方法

基本はfunction命令か、関数リテラル、アロー関数を用いる。

①function命令

function 関数名(引数,...){
~~任意の処理~~
  return 戻り値;
}

※showMessageのように「動詞+名詞」の形式で命名するのが一般的。

②Functionコンストラクター経由 ※Functionオブジェクト

var 変数名 = new Function(引数,...関数の本体);

※function命令と違い、引数や関数本体を文字列として定義できる。

③関数リテラル

名前のない関数を定義した上で、変数に格納する。

var 変数名 = function(引数,...){
  return 戻り値;
};

④アロー関数

シンプルに記載可能。functionキーワードを用いない。代わりに、=>(※アロー)で引数と関数本体をつなぐ。

(引数,...) => {...関数の本体...}
let 変数名 = (引数,...) => 関数 // 本体が1文の場合。
let 変数名 = 引数 => 関数 // 引数が1個の場合。

本体が1文の場合、{}を省略可能。さらに、文の戻り値が戻り値とみなされ、return命令も省略可能。

引数が1個の場合は引数のカッコも省略可能。(※引数がない場合のカッコの省略は不可。)

📝コンストラクタ関数 参考

オブジェクトを生成するための関数。(※実際は普通の関数と全く同じ。ただ関数の中でオブジェクトに用意する値などの設定を行う処理を記載するだけ。)

関数と見分けがつきにくいので頭文字を大文字にすることが慣習。

var Class = function(){};

👉1つの関数にプロパティやメソッドを記載するとわかりにくくなるため、ES2015からはクラス宣言ができるようになった。

📝class宣言

class クラス名 {
  ~~コンストラクターの定義(必要な初期化処理を用意)~~
  ~~プロパティの定義~~
  ~~メソッドの定義~~
}

おわりに

※4/30時点

JSの関数定義はしっかりマスターしたいと感じた。

細かい部分の深堀(2周目)はTypeScriptの学習と併行しながら実施しようと思います。

またasync/awaitの登場がES8からの登場だったのを知ったときは、今までのモヤモヤがとてもスッキリした。。。笑

(Progateでアウトプットしようかな。。。)

追記5/25:

パーフェクトJavaScriptを読んで例えば文字列型と文字列オブジェクト、なぜnewを付けるのかなど細かい部分をしっかり理解していきたい。

また、プロトタイプ(P139~)やクロージャ(P159~)などあいまいな部分も多く、かつ理解が難しかったので、改めて本格入門を読み直しても良いかもしれない。

とりあえずVScodeで実際にターミナルで出力を確認しながら学習していく方法を覚えたので一歩前進。

✅参考

💻JavaScript での変数定義は var を捨てて let, const を使うべき理由

影響範囲を狭くするためにvarは利用しないほうが良いらしい。

学習の備忘録

📝用語

・識別子:変数名や関数名など、開発者がプログラムの中で定義する単語。⇔予約語(nullやtrueなど)は識別子にできない。

📚本格入門JSの学習記録

P108~P174 組込関数に関して
P224~ 以降ざっくり。

📚パーフェクトJavaScriptの学習記録

5/25 P54まで
5/26 p112 関数の引数交換曖昧、p126プロパティの列挙、P139~のプロトタイプチェーン曖昧、

📚JS超入門

縦に並べたくなるようなものは配列、横に並べたくなるようなものはオブジェクトを選ぶのがおすすめ。

💻今すぐ使えるJavaScriptを実行する環境まとめ

以下のように記載するとブラウザ上部URLエリアで実行できる。

javascript:window.confirm('Hello');

コンソールであればVScodeでこの使い方が一番良さそう。

node sample.js

 

コメントを残す