説明
/**
* const, let
*/
// 昔からの var
var val1 = 'var変数';
console.log(val1);
// 問題点:varは上書き可能
var val1 = 'var変数を上書き';
console.log(val1);
// 問題点2:varは再宣言可能
var val1 = 'var変数を再宣言';
console.log(val1);
// let
let val2 = 'let変数';
console.log(val2);
// letは上書き可能
val2 = 'let変数を上書き';
console.log(val2);
// letは再宣言不可能
// let var2 = 'letで変数の再宣言はエラーになる';
// const
const val3 = 'const変数';
// const変数は上書き不可
// val3 = 'const変数は上書き不可。エラーになります';
// constは再宣言不可
// const val3 = 'constは再宣言できません。エラーになります。';
// constで定義したオブジェクトはプロパティ値の変更が可能である。プロパティ自体を追加することもできる。
const val4 = {
name: '山田',
age: 20,
};
console.log(val4);
val4.name = '山本';
val4.address = '東京'; // 新しいプロパティの追加もできる
console.log(val4);
// ちなみにJavaScript に「プロパティ名そのものを直接書き換える」という機能は存在しません。
// プロパティ名を変更する手順
// 新しい名前でプロパティを作成し、元の値を代入する。
// 古い名前のプロパティを delete 演算子で削除する。
// 分割代入とスプレッド構文で、nameをnewNameとして取り出し、残りをrestに入れる
const { name: newName, ...rest } = val4;
// 新しいオブジェクトを再構成
const updatedVal = { newName, ...rest };
console.log(updatedVal);
// 結果: { newName: "山田", age: 20 }
// constで定義した配列は要素の変更が可能である
const val5 = ['dog', 'cat'];
val5[0] = 'bird';
val5.push('monkey');
console.log(val5);
/**
* テンプレート文字列
*/
const name2 = '山田';
const age = 40;
// わたしの名前は山田です。年齢は40です。
// 従来の方法
const message1 = '私の名前は' + name2 + 'です。年齢は' + age + '歳です。';
console.log(message1);
// テンプレート文字列。 バッククォートの中に文字列や変数をかける
const message2 = `私の名前は${name2}です。年齢は${age}です。`;
console.log(message2);
/**
* アロー関数
*/
// 従来の関数の書き方
function func1(str) {
return str;
}
console.log(func1('func1です。'));
// アロー関数
const func2 = (str) => {
return str;
};
console.log(func2('func2です。'));
// アロー関数:省略記法 引数が一つの時、( )を省略できる
const func3 = str => {
return str;
};
// アロー関数:省略記法 関数の中身が単一式で終わってreturn で返却する場合、{ } と return を省略できる。(注釈1)
// 見分け方は = と =>
const func4 = (str) => str;
// アロー関数:省略記法 注意。{ } で囲っている場合、必ず return が必要
const func5 = (str) => {
return str;
};
// アロー関数の使用例1
const add = (x, y) => {
return x + y;
};
// アロー関数の使用例2. 単一行で値を返すだけなので{}とreturnは省略できる
const add2 = (x, y) => x + y;
// アロー関数の使用例3。 returnを省略している
const func6 = (x, y) => ({ hoge: x, hogu: y });
// アロー関数の使用例4 return省略。上記と同じ意味。オブジェクトはreturn省略して、単一行で返せるが、オブジェクトの定義が複数行に渡る場合、({ }) のように( )で囲えば、オブジェクトが複数行でも、単一行として返せる
const func7 = (x, y) => ({
hoge: x,
hogu: y,
});
(注釈1)
「その1つの式の値をそのまま戻り値(return)にしたい場合」 という表現が最も正確です。
納得感のある説明案: 「関数の処理が 『1つの値を評価して返すだけ』 の場合、{ } と return をセットで省略して書くことができます。ただし、console.log のように値を返すのが目的でない処理も書けますが、その場合は関数の戻り値が undefined になります。」
まとめ
計算結果を返したい: 省略して書くのがスマート。
console.log や命令を実行したいだけ: { } を書いてもいいし、省略しても動く(けど戻り値に注意)。
説明続き
/**
* 分割代入
*/
// 分割代入(Destructuring assignment)の本質は、「右側の値をバラして、左側で宣言した『新しい変数』に代入する」 という行為です。
const myProfile = {
nickName: 'たぴおか',
age2: 30,
};
// オブジェクトのプロパティ表示
const message3 = `名前は${myProfile.nickName}です。年齢は${myProfile.age2}です。`;
console.log(message3);
// 分割代入 オブジェクトの分割代入
const { nickName, age2 } = myProfile;
const message4 = `名前は${nickName}です。年齢は${age2}です。`;
console.log(message4);
// オブジェクトの場合: const { nickName, age2 } = myProfile; こちらも同様に、nickName という名前の 変数 をその場で宣言しています。たまたま元のオブジェクトの「プロパティ名(キー)」と同じ名前を使っているだけ、という解釈になります。
// 分割代入 配列 分割代入使わないパターン
const myProfile2 = ['タピオカ', 20];
const message5 = `名前は${myProfile2[0]}です。年齢は${myProfile2[1]}歳です。`;
console.log(message5);
// 分割代入 配列 分割代入パターン 配列は元々の情報にindexと値しかないので、自分で好きな変数名を決める
const [name6, age6] = myProfile2;
const message6 = `名前は${name6}です。年齢は${age6}です。`;
console.log(message6);
//配列の場合: const [name6, age6] = myProfile2; ここでは、新しく name6 と age6 という名前の 変数(Variable) を作って、そこに配列の中身を詰め込んでいます。配列の側にあるのは「要素」ですが、それを受け取る側は「変数」になります。
// 配列の分割代入は配列が持っている順番が大事になってくるので、そこは気をつける
/**
* デフォルト値(引数、分割代入)
*/
// デフォルト値がない関数
const sayHello = (name7) => console.log(`こんにちは!${name7}さん。`);
sayHello('タピオカ'); //こんにちは!タピオカさん。
sayHello(); //こんにちは!undefinedさん。
// デフォルト値がある関数
const sayHello2 = (name8 = 'ゲスト') =>
console.log(`こんにちは!${name8}さん。`);
sayHello2(); // こんにちは!ゲストさん。
// デフォルト値 オブジェクト
const myProfile3 = {
age9: 50,
};
const { age9, name9 } = myProfile3;
console.log(age9); // 50
console.log(name9); // undefined
const { age10, name10 = 'ゲスト' } = myProfile3;
console.log(age10); // 50
console.log(name10); // ゲスト
/**
* オブジェクトの省略記法
*/
// オブジェクトの定義 省略しない書き方
const name11 = 'タピオカ';
const age11 = 10;
const myProfile4 = {
name11: name11,
age11: age11,
};
// オブジェクトの定義 省略する書き方
const name12 = 'タピオカ';
const age12 = 30;
const myProfile5 = {
name12,
age12,
};
console.log(myProfile5);
// オブジェクトの定義 省略する書き方 1行で書いた場合
const myProfile6 = { name12, age12 };
console.log(myProfile6);
/**
* スプレッド構文 ...
*/
// スプレッド構文の使い方1 配列の展開
const arr1 = [1, 2];
console.log(arr1); // [1, 2]
console.log(...arr1); // 1, 2
const sumFunc = (num1, num2) => console.log(num1 + num2);
console.log(sumFunc(arr1[0], arr1[1])); // 3
console.log(sumFunc(...arr1)); // 3 上記と同じ結果になる
// スプレッド構文の使い方2 まとめる
const arr2 = [1, 2, 3, 4, 5];
const [num1, num2, ...arr3] = arr2;
console.log(num1); // 1
console.log(num2); // 2
console.log(arr3); // [3, 4, 5]
// スプレッド構文の使い方3 配列のコピー、結合
const arr4 = [100, 200];
const arr5 = [300, 400];
// 配列のコピー
// arr4をarr6という変数名でコピーしたい時
// こうすると、...4 という展開したものをまた[]配列の中に入れていることになる。それをarr6という変数に代入している
const arr6 = [...arr4]; // [100, 200]
// 配列の追加
const arr7 = [...arr4, ...arr5];
console.log(arr7); // [100, 200, 300, 400]
// 配列のコピー 参照
const arr8 = arr4; // これは参照なので、よくない。同じ場所を参照している
console.log(arr8); // [100, 200]
arr8[0] = 1000;
console.log(arr8); // [1000, 200]
console.log(arr4); // [1000, 200] arr4まで上書きされている。
/**
* mapやfilterを使った配列の処理
*/
// map
const nameArr = ['田中', '山田', 'タピオカ'];
// 従来からのfor文
for (let index = 0; index < nameArr.length; index++) {
console.log(nameArr[index]);
}
// forと同じ処理をmapを使ってやる場合
nameArr.map((name) => {
console.log(name);
});
// 上記は1行でかける
nameArr.map((name) => console.log(name));
// mapの中でreturnし、新しい配列を作成
const nameArr2 = nameArr.map((name) => {
return name;
});
console.log(nameArr2); // ['田中', '山田', 'タピオカ']
// filter
const numArr = [1, 2, 3, 4, 5];
const newNumArr = numArr.filter((num) => {
return num % 2 === 1;
});
console.log(newNumArr); // [1, 3, 5]
// 何番目の要素か知りたい場合 for
for (let index = 0; index < nameArr.length; index++) {
console.log(`${index}番目は${nameArr[index]}さんです。`);
}
// 何番目の要素か知りたい場合 map
nameArr.map((name, index) =>
console.log(`${index + 1}番目は${name}さんです。`)
);
// mapを使ったレッスン
// 自分(タピオカ)以外はさんをつける。
const nameArr3 = ['いちご', 'パイナップル', 'タピオカ'];
const newSuffixArr = nameArr3.map((name) => {
return name !== 'タピオカ' ? `${name}さん` : name;
});
console.log(newSuffixArr);
/**
* 三項演算子
*/
// 例1
const val = 1 > 0 ? 'trueです。' : 'faleです。';
console.log(val);
// 例2
const num3 = 1300;
console.log(num3.toLocaleString());
const num4 = '1300';
console.log(num4.toLocaleString());
// 三項演算子の練習
// 数値だったら3桁区切りにする。数値でない時は数値を入れてくださいと出す。
const num5 = 4500;
const formattedNum =
typeof num5 === 'number' ? num5.toLocaleString() : '数値を入力してください';
console.log(formattedNum);
const checkSum = (num1, num2) => {
return num1 + num2 > 1000 ? '1000を超えています。' : '許容範囲内です。';
};
console.log(checkSum(400, 500));
console.log(checkSum(501, 500));
/**
* 論理演算子 && ||
*/
// truthy: "AAA" 10 [] {}
// falsy: 0 undefined null false NaN "" そして BigInt の 0n
const val7 = 0;
if (val7) {
console.log('val7はtruthyです。');
} else {
console.log('val7はfalseです。');
}
// NaN は自分自身とさえ一致しない これでは常にfalseになる
const val8 = NaN;
console.log(val8 === NaN); // false !?
// .isNaN() で判定すること
if (Number.isNaN(val8)) {
console.log('これはNaNです!');
}
// 論理演算子の使い方(短絡評価 短絡演算)
// || は左側がtruthyの時、その時点で値を返却する
const number2 = 1000;
const fee = number2 || '金額未設定です。';
console.log(fee); // 金額未設定です。
// || は左側がfalseyの時、左側の値を返却する。
const number = null;
const fee2 = number || '金額未設定です。';
console.log(fee2); // 金額未設定です。
// && は左側がfalsyの時その時点で返却する
const number4 = null;
const fee4 = number4 && '何か設定されました';
console.log(fee4);
// && は左側がtrusyかつ右側もfalsyの時右側を返却する
const number3 = 1000;
const fee3 = number3 && '何か設定されました';
console.log(fee3);