アロー関数
function fn(number) {
return number * 2;
}
上記をアロー関数に変換する
・引数の表示
引数が2つなら
const fn = (number1, number2,...) => {
return number * 2;
}
引数が一つなら
const fn = number => {
return number * 2;
}
・関数ないの記述
関数記述が1行なら
const fn = number => return number * 2;
関数記述が2行なら
const fn = number => {
console.log(2);
return number * 2;
}
関数記述が1行でオブジェクトを返すなら
()で括る
const fn = number =>({result:number*2});
ESモジュールについて
Javascriptのファイルを一つのモジュールという単位にして、このファイルごとに機能を管理する。
使う際にはexportして利用する
main.js
import { hello } from "./module.js";
// モジュールバンドル(webpack)を使う際にはjs拡張子が補完されるが、
// htmlファイルについては、jsまで記載
import { User } from "./module.js";
// 同じファイルからであれば、1行にまとめることも可能(export)
import {hello,User } from "./module.js"
import funcB from "./module.js"
// default が一つしかないので、
//{}は不要
// 好きな名前を記載できる
//上記全て同じファイルの場合
import funcB, {hello,User} from "./module.js"
hello();
const user = new User('Tom');
user.hello();
//
module.js
export const hello = () => {
console.log("hello!");
};
const funcB = () => {
console.log("funcB output");
};
export default funcB;
class User {
constructor(name) {
this.name = name;
}
hello() {
console.log(this.name);
}
}
export { User }
// 外部からアクセスさせたくない関数を定義した場合には、先頭にexportせずに
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>開始時点コード</title>
</head>
<body>
<h1>開始時点コード</h1>
<script type="module" src="main.js"></script>
<!-- es moduleを使うにはtype moduleを使う必要がある -->
<!-- reactではesモジュールのコードをjaavascriptに変換する処理が入っている。 -->
<!-- 直接index.htmlから読み込む際には type="module"が必要-->
</body>
</html>
コールバック関数
コールバック関数とは引数に渡された関数を指す
function print(callback) {
const result = callback();//これ
console.log(result);
}
function fn(number = 3) {
// 初期値として3を設定する。
// 初期値がないとコールバック関数を使った場合にはnumberがundefinedとして定義される。
return number * 2;
}
debugger;
// デバッガーにてコンソールにてフローが確認可能
print(fn);
// ここでは引数numberがなし(undefined)のため、結果としてNaNとなる。
DOMとイベントリスナーについて
DOMとはHTMLのタグをJSから操作するときに使用するもの
const h1Element = document.querySelector('h1');
console.log(h1Element);
console.dir(h1Element);
// DOMオブジェクトの実態
// プロパティの形式
console.log(h1Element.textContent);
h1Element.textContent = "変更後のタイトル"
// オブジェクトの形式でHTMLにアクセスする
// ノード、エレメントとも呼ぶ
const btnEl = document.querySelector('button');
//イベントリスナーに設定されている場合
btnEl.addEventListener('click', (e) => {
// 第一引数:イベント名
// 第2引数:実行する関数(コールバック関数)
console.dir(e.target.text);
// e:イベントのオブジェクト
// 発火に伴うオブジェクトが参照可能 .dir
console.log('hello');
})
// 関数を別に定義した場合
const fn = (e) => {
// fnを下記にてコールバック関数として定義
// eは関数が実行されるときにセットされて渡される。
console.dir(e.target.text);
// e:イベントのオブジェクト
// 発火に伴うオブジェクト
console.log('hello');
}
btnEl.addEventListener('click', fn);
// fnが実行可能な状態になる。
配列のmap,filter
for文などを使うことによって記述量が長くなり、ごちゃごちゃしてしまうため、
map,filterを使うことにより、記述量を減らし可読性をあげることができる。
const arry = [10, 20, 30, 40];
const newArry = [];
for (let i = 0; i < arry.length; i++){
newArry.push(arry[i]*2)
}
console.log(newArry)
// 上記をmapメソッドで
const newArry2 = arry.map(val => {
console.log(val)
// arryの値が順番に格納されている。
return val * 3;
});
console.log(newArry2);
const newArry3 = arry.map((val, i, arry) => {
// (val,i,arry):実際に定義できる
console.log(val)
return val * 3;
});
// filterメソッド
for (let i = 0; i < arry.length; i++){
const val = arry[i] * 2;
if (val > 50) {
newArry.push(arry[i]*2)
}
}
const newArry4 = newArry2.filter(val => {
return val > 50
});
// コールバックする関数がリターンする値がtrueであれば条件が追加される
console.log(newArry4)
// filtrとマップを一緒に使う場合には
const newArry5 = arry.map(val => val * 2).filter(val => val > 50);
console.log(newArry5)
分割代入
分割代入というのは、配列やオブジェクトの特定の要素を変数として抽出する
const arry = ["配列1", "配列2", "配列3"];
console.log(arry[0]);
console.log(arry[2]);
const [a, b, c] = ["配列1", "配列2", "配列3"];
// 下記のように取り出したい部分だけ定義でもOK
const [d, , e] = ["配列1", "配列2", "配列3"];
const [d] = ["配列1", "配列2", "配列3"];
console.log(a);
console.log(b);
const obj = { x: "オブジェクト1", y: "オブジェクト2", z: "オブジェクト3" };
console.log(obj.x);
console.log(obj.y);
const {x,z} = { x: "オブジェクト1", y: "オブジェクト2", z: "オブジェクト3" };
// const {z,x}〜としても、オブジェクトの分割代入はプロパティ名と一致させる必要がある。
console.log(x);
console.log(z);
const arr = ["Japan", "Tokyo", "Shinjuku"];
const objAddress = { state: "Tokyo", country: "Japan", city: "Shinjuku" };
const fnArr = (arry) => {
console.log("---配列---");
console.log(`country: ${arry[0]}`);
console.log(`state: ${arry[1]}`);
console.log(`city: ${arry[2]}`);
};
const fnArr2 = ([country, state, city]) => {
// 配列は順番に気をつける
console.log("---配列---");
console.log(`country: ${country}`);
console.log(`state: ${state}`);
console.log(`city: ${city}`);
};
const fnObj = (objAddr) => {
console.log("---オブジェクト---");
console.log(`country: ${objAddr.country}`);
console.log(`state: ${objAddr.state}`);
console.log(`city: ${objAddr.city}`);
};
// 分割代入パターン
const fnObj2 = ({country,state,city}) => {
console.log("---オブジェクト---");
console.log(`country: ${country}`);
console.log(`state: ${state}`);
console.log(`city: ${city}`);
};
fnArr(arr);
fnObj(objAddress);
スプレッド演算子、レストパラメータ
スプレッドを使う場合には、使わない場合に比べて意味合いが変わるので注意する。
スプレッドの場合には、あくまで新規配列に要素を展開するために内容が異なる。
const nums = [3, 1, 4, 1, 5, 10, 2, 6];
const result = Math.max(3, 1, 4, 1, 5, 10, 2, 6);
// スプレッドを使う場合には、使わない場合に比べて意味合いが変わるので注意する。
// スプレッド演算子を利用した場合
// 配列の要素を展開する場合
const result2 = Math.max(...nums);
console.log(result);
let arr1 = [1, 2, 3];
let arr2 = [4, 5, 6];
let newArr = [...arr1];// 要素が展開されて、新しい配列となる。
console.log(newArr);
// スプレッド演算子で展開した場合、等価演算子で確認するとfalseになる。>別物
console.log(newArr === arr1);
newArr.push(5);
// 参照先が異なるので、
console.log(newArr, arr1)
let newArr1 = arr1
// 通常代入した場合で展開した場合、等価演算子で確認するとtureになる。
console.log(newArr1 === arr1)
// 代入した場合には参照している配列が同じ
// 通常代入はあくまで参照先を同じにしている。
newArr1.push(4);
console.log(newArr1,arr1)
let newArr3 = [...arr1, 10, ...arr2];// 要素が展開されて、新しい配列となる。
console.log(newArr3);
const obj = {
name: "Tom",
age: 22,
};
const newObj = { ...obj };
newObj.name = 'John';
console.log(newObj);
console.log(obj);
// スプレッド演算子を用いた場合には元の配列に影響を及ぼさない。
// レストパラメータ、残よ引数:(...argA)
// 可変数の引数に利用する場合
const restA = (...argA) => console.log(argA);
restA(1, 5, 4)
const restB = (n, ...argB) => console.log(argB,n);
restB(1, 3, 4)
三項演算子
条件変数 ? trueの場合 : falseの場合
// 三項演算子( ? : )
const a = false;
let resultA = a ? "true": -10;
// 条件変数/ trueの場合/falseの場合
console.log(resultA);
if(a) {
resultA = "true";
} else {
resultA = "false";
}
console.log(resultA);
function getResult() {
return a ? "true" : "false";
}
console.log(getResult());
truthy falthy 論理話 論理積
// falsy → 真偽値に変換した際に"偽(false)"とみなされる値のこと。
// truthy → それ以外
/* falsyな値の一覧
false
0 (数字)
0n (big int)
"" (空文字)
null
undefined
NaN (Not a Number)
*/
const a = 0;
let result = a ? 10 : -10;
console.log(result);
const falsy = 0;
const truthy = 1;
// 確認する手段
console.log(Boolean(truthy));
console.log(Boolean(falsy));
// 論理積 (&&) について
const resultA = "" && "foo"; //""が格納
const resultB = 2 && 1 && 0 && 3; //0を返す
const resultC = "foo" && 4; //4(右側を返す)
// console.log(resultA);
console.log(resultB);
console.log(resultC);
// 理論和 (||) について
const resultD = "" || "foo";
const resultE = 0 || 2 || 0; //truthyが見つかったものを返す(2)
const resultF = "foo" || 4; //truthyが見つかったものを返す(foo)
console.log(resultD);
console.log(resultE);
console.log(resultF);
非同期処理 Promise
非同期処理が終わった後に特定の処理をつなげるときに使うのがPromise
let a = 0;
console.log(a);
new Promise((resolve, reject) => {
// 引数には上記2つの関数が渡る。
setTimeout(() => {
a = 2;
resolve(a);
reject(a);//エラー時に使う
// 順番通りに動かない:非同期処理
}, 2000);
}).then((b) => {
// resolve()が呼ばれるとthenが実行される。
console.log(b);
return b;
// returnで返す値が次のthenへ
}).then((b) => {
// resolve()が呼ばれるとthenが実行される。
console.log(b+1);
}).catch((a) => {
// rejectが呼ばれるとcatchが実行される。
// エラー時につながる
console.log('error')
})
setTimeout(() => {
a = 1;
console.log(a)
// 順番通りに動かない:非同期処理
}, 3000);
await async
// 非同期処理(Promise)
let a = 0;
// thenメソッドを使わないので便利になる
init();
async function init() {//awaitの使った関数の先頭にasyncをつける
// 例外処理
try {
const result = await new Promise((resolve, reject) => {
// resolveが呼ばれるまでこのawaitで書いた行で処理が待機するので終わり次第、次の行へ
setTimeout(() => {
a = 2;
reject(a)
// resolve(a)
}, 2000);
})
} catch (e) {
// 慣例的にeで引数が渡される。
console.log('catchが実行',e)
}
console.log(result);
}