参考
【JS】ガチで学びたい人のためのJavaScriptメカニズム
あらすじ
現場でrailsを触ってlaravelを触って今はtypescriptとreact-routerで実装することが多くなってきたが、今までJavascriptをがっつり勉強してなかったので復習も兼ねて上記講座を受けてみようと思った。
とある先輩から「エンジニアじゃない人間が聞いてもわかる程度の説明にしろ」という言葉をいただいたので、できるだけ頑張る。
変数とは
値(データ)を受け取る箱
JSではvar
,let
,const
がある。
- var
関数スコープ。再宣言、再代入が可能。 - let
ブロックスコープ。再代入が可能。 - const
ブロックスコープ。再宣言、再代入不可能。
//再宣言
var hoge = a;
var hoge = b; //これは可能
//再代入
let hoge= a;
a = fuga; //これは可能
また、var
は関数スコープのため、変数宣言は巻き上げが可能となる。
function fn(makiage){
console.log(makiage); // undefinedと出力される
var makiage = '巻き上げなう';
}
fn();
// 内部的には以下のように解釈される
// var makiage; // 宣言が巻き上げられる
// console.log(x); // undefined
// makiage = '巻き上げなう'; // 代入はそのままの位置
巻き上げができない例
function fn(makiage){
console.log(makiage);
const makiage = '巻き上げなう';
}
fn();
// ReferenceErrorと出力される
// varは初期値にundefinedを入れてくれるがlet、constはしてくれないため
// 以下は出力される。
function fn(makiage){
console.log(makiage);
}
const makiage = '巻き上げなう';
fn(makiage);
主なデータ型
JSで主に以下のデータ型がある。
型 | 英名 | 例 |
---|---|---|
真偽値 | Boolean | true/false |
数値 | Number | 12 |
文字列 | String | "Hello" |
undefined | undefined | undefined |
null | Null | null |
シンボル | symbol | 一意の意味 |
BigInt | BogInt | 12n |
オブジェクト | Object | {a: value} |
個人的には数値をintと勘違いするので気をつけたい。
※undefinedとnullの違い
null = トイレットペーパーの芯だけの状態
undefined = そもそもトイレットペーパーがセットされてない
暗黙的な型変換
JavaScriptは暗黙的に型変換を行なってしまう。
暗黙的な型変換は片方が優先される。
function printTypeAndValue(val) {
console.log(typeof val, val);
}
let a = 0;
printTypeAndValue(a);
// Number 0
let b = '1' + a;
printTypeAndValue(b);
// '10'
// 最初が文字列なので文字列結合として扱われる
let e = 5 - true;
printTypeAndValue(e);
// これは5がint、trueがbooleanだが、booleanでのtrueは1、falseは0なので
// intに置き換えられて4と出力される
厳格な等価性と抽象的な等価性
イコールの形で評価が変わる。
イコール一つは代入なのでここでは説明なし。
===
なら型も含めて評価する
==
なら見た目で評価する。
手間暇かけた方が厳格に判断できるってこと。
// 厳格:
a===b //(型比較あり)
// 抽象:
a==b //(型比較なし)
falselyとtruthly
falslyな値=booleanで真偽値に変換した場合、falseになる値
fanselyの例: false,null,undefined,0,NaN,a
値が入っているかどうかはいろんなとこで使うので
以下のイディオムは覚えておくのが吉。
以下は値が入っていれば処理を行う。
if (hoge){
// 処理
}
逆に以下の場合は値が入っていなければ処理を行う
if (!hoge){
// 処理
}
ただし上記の場合、値が整数0
の時もfalseに分類されるので注意。
AND条件とOR条件
&&
-> AかつB
||
-> AまたはB
ここで気をつけたいのが
&&はfalseがあればその時点で評価が終わる
||はtrueがあればその時点で評価が終わる
a = 1;
b = 0;
c = 3;
console.log(a && b && c);
// 0が出力される
console.log(a || b || c);
// 1が出力される
よく使う例
name = name || 'tom';
// nameがあればname、false(null等)は'tom'とする
name = name ? 'taro' : 'tom';
// nameがあれば'taro'、false(null等)は'tom'とする
プリミティブ型とオブジェクト
- プリミティブ型
オブジェクト型以外のものをプリミティブ型という。immutable(不変)の性質を持ち、変数には値が入る。一度作成したらその値は更新できない。
ここでいう更新できないのは以下のように
let a = 'Hello';
a = 'Bye';
のようにしてもlet a = 'Hello'
はメモリ上に残るということ。
- オブジェクト
変数には参照が格納される。値を変換できる。
オブジェクトとは、名前付きの参照を管理する入れ物。
参照
オブジェクトで使う考え方
let c = {
prop: 'hello'
}
let d = c;
d.prop = 'bye';
console.log(c, d);
// これはどっちもbyeが入る
オブジェクトに関して、値は変更できないが、プロパティは変更できる。
let c = {
prop: 'hello'
}
let d = c;
// d.prop = 'bye';
d = {};
console.log(c, d);
// これはhelloと{}が返る
ちなみにconstだと
const a = 'hello';
a = 'bye'; // これはNG
constはロックがキーワードで、プリミティブの場合、値のコピー(参照行為)がロックされる。だからconstは上書きできない。
同様にオブジェクトも
const a = {
prop: 5;
}
a = {} //これはNG
これはオブジェクトのa->{}(ブロックの中身)->prop->5の道筋の中でa->{}の部分の参照がロックされるので置き換えることができない。ただし、{}->propとprop->5の参照はロックされていないので入れ替えが可能
a.prop = 5 //これはOK
なので以下のようにオブジェクトの中身を変えることもできる。
良い反面、値が追いにくくなるので書くときに注意。
const a = {
prop: 5;
}
const b = a
a.prop = 6
b.newprop = 10
console.log(a); // { prop: 6, newprop: 10 }
console.log(b); // { prop: 6, newprop: 10 }
console.log(a === b); // true (同じオブジェクトを参照している)
分割代入
分割代入すると新しいオブジェクトを作成するので元のオブジェクトに影響がないように作成できる
// 1. 最初の状態
const a = {
prop: 'hello'
};
// 2. 分割代入
const { prop } = a; // prop = 'hello' として新しい変数を作成
prop = 'bye';
console.log(a.prop); // 'hello' (元のオブジェクトは変更されていない)