JavaScript基礎 演算子とループ文
JavaScriptでの演算子についてわからない部分をまとめていきます
そもそも演算子の定義から、
演算子とは値をもとに何らかの処理を行い、その結果を返す記号のことです。
演算子とは硬い物言いですが要するに足し算引き算などの記号のことでプログラミング言語では、もう少し複雑な演算子があります
また、演算子には優先順位があり少し調べれば、一覧表が出てくるため覚える必要はなさそうです
単項演算子
delete演算子
delete Object.propathy
のように記述します
オブジェクトのプロパティを削除する際に使用します
type of演算子
こちらはデータ型の確認に使用します
instanceof演算子
instanceofは、オブジェクトがクラスのインスタンスかどうかを判定する演算子です。
class a{} class b extends a{} const c = new b(); console.log( c instanceof a ); // true console.log( c instanceof b ); // true
classのコンストラクター関数やプロパティ、あるいは継承したclassのインスタンスでも判定が真になります
Null合体演算子 ( ?? )
Null合体演算子 ( ?? )は変数に初期値を設定する時に使用される演算子です
左のオペランドがnullまたはundefinedの場合に右のオペランド返します
それ以外には左の演算子を返します
使い方
let var = null;
val = val ?? "初期値";
console.log(val);
> 初期値
また、論理積で判定する以外にも論理和( || )で判定する方法もありこちらはfalsyな値、例えば0や空文字でも右辺のオペランドが返るようになります
let val = "";
val val || "初期値";
console.log(val);
> 初期値
なお今回の例では分かりやすく変数宣言でnullを設定してから判定していますが、実際はプログラムのどこかでnullまたはundefinedが設定されていそうなコード上の変数に対してNull合体演算子を使用します
オプショナルチュイニング演算子 (?.)
オプショナルチュイニング演算子 ( ?. )はオブジェクト以外の値に対してプロパティを取得した時にundefinedを返す演算子です
通常オブジェクトのプロパティの値を取得する際にはドット演算子 ( . )を使いますが、ドット演算子では左オペランドがオブジェクトではなかった場合にエラーになり処理が止まってしまいます
プロパティを保持できるのはオブジェクトのみのため、どこかの処理でundefinedが返ってしまっていた場合、エラーで処理が止まってしまうのはまずいので、undefinedでスルーしたい場合が多々あります
let user = {}; // ユーザは address を持たない alert( user?.address?.street ); > undefined (エラーは起きません)
別にこの演算子だけの話ではないですが、他にも値が存在するかの確認方法としてはif文であったり三項演算子での識別ももちろん可能ですが、より簡潔に記述するためにいろいろな方法をマスターしておく必要があると感じました
for ループ ( 各種 )
ここでは繰り返し処理のfor文のおさらいをしていこうと思います
for文を利用するときの用途としては「ループしたい回数が決まっている」という状況です
回数が分からないけど要素が存在する限りループしたい場合はwhile
を選択しましょう
そしてすべてのforループ文は実行する文が一つだけだった場合、{}
を省略することが出来ます
まずは基本
for (let i = 0; i < array.length; i++) {
//この中で処理を書く
}
とこれが基本的な形になるわけですが、派生技でカンマ演算子を使って複数の変数に対して初期化を行ったり値の変化を行うことも出来ます
簡単な例です
for (let i = 1, j = 4; i < 5; i++, j--){
console.log("i = " + i + ", j = " + j);
}
>> i = 1, j = 4
>> i = 2, j = 3
>> i = 3, j = 2
>> i = 4, j = 1
なかなかこういう使用方法はないと思います。こういうこともできるよ〜くらいに覚えておきます
for in
さてこちらはオブジェクトに対して使用するループ文です
for( 変数 in オブジェクト ) {
// 処理を書く
}
ループ処理の流れとしては、まずオブジェクトが null か undefined だった場合には for…in 文は終了します
それ以外だった場合にはオブジェクトからプロパティ名が変数に格納され、そのあとでブロック内の処理が実行されていく流れなので主に変数のプロパティを使用して処理を書いていきます
取得できるプロパティが無くなれば自動的に処理は終了です
プロパティ名は文字列の値として変数に格納されます。そのため、プロパティ名を使ってプロパティの値を参照する場合は、 オブジェクト名.プロパティ名 の形式ではなく オブジェクト名[プロパティ名] の形式を使用する必要があります。
オブジェクトへのアクセス方法でブラケット記法でないとプロパティ名に変数を使用できないルールがあるためです
列挙可能性について
オブジェクトの仕組みとしてループしても表示されない、またはループに組み込まれてしまう列挙可能性という概念が存在します
これの設定はプロパティ記述子(ディスクリプタ)と呼び、オブジェクトのプロパティの隠し設定のようなものです
その設定を確認する関数です
const プロパティ記述子 = Reflect.getOwnPropertyDescriptor(オブジェクト名, "プロパティ名");
const obj = { prop: "値" }; const propDesc = Reflect.getOwnPropertyDescriptor(obj, "prop"); console.log(propDesc);
これをコンソールで確認し列挙可能性の設定はenumerableを変更します(デフォルトはtrue)
変更用のメソッドです
Reflect.defineProperty(設定対象オブジェクト, "プロパティ名", プロパティ記述子);
今度記述するプロトタイプの記事で詳しく掘り下げたいと思いますが、実際の開発現場ではhasOwnProperty
を使用するのが一般的なようです
for( var key in items ) { if( items.hasOwnProperty(key) ) { console.log( key + ': ' + items[key] ); } }
オブジェクト.hasOwnProperty(プロパティ名)
hasOwnProperty
はオブジェクトに指定のプロパティが存在するか調べるメソッドであるためこれで予期せぬデータが引っ張られてくることもなくなります
for inと Symbolについて
ES6で追加されたSymbol型のプロパティもfor in
の列挙対象にならないため、注意が必要そうです
先に紹介した列挙可能性をtrue
にしてもfor in
では列挙出来ないようです
for of文
これも私はあまり使用していなです、、forEach使っちゃう 笑
for of文では反復可能オブジェクトに対する繰り返し処理記述できます。反復可能オブジェクトとは、固く言いましたが、メインは配列や配列ライクなもので、
オブジェクトに対してはfor in
を使用し、配列に対してはfor of
を使用するなどと覚えておくと良さそうです
for…of文の記法
- for (const value of iterable) { //繰り返し処理}
- value: 要素の値が渡される。反復可能オブジェクトの種類によって値が変わります<br> 配列やSetの場合は値が。Mapの場合はプロパティと対になった配列が<br> [プロパティ,値] という形式で渡されます
イテラブル・オブジェクト
イテラブル・オブジェクトとは反復可能かどうかという定義です
配列そのものをコンソールに表示させると「__proto__
」プロパティが最下部あたりにあると思いますが、これを展開した時に表示される「Symbol.iterator
」が、イテラブル・オブジェクトになります。
したがってこれがあるかないかで反復可能オブジェクトかそうでないかが決まりますが、イテラブル・オブジェクトは自分で作成することも可能なのでそれはまたの機会に、、
オブジェクトに対してfor…of文を使用する
オブジェクトリテラルで定義したオブジェクトは反復可能オブジェクトではないため、
オブジェクトの静的メソッドを使うことで利用可能な配列へと変換して使用する方法がモダンで有用のようです
プロパティの配列を取得する場合
const プロパティの配列 = Object.keys(オブジェクト);
これでオブジェクトの中からプロパティだけを抜き出した配列が作成できます
const fruits = { apple: "リンゴ", banana: "バナナ" }; const props = Object.keys(fruits); console.log(props); // > ["apple", "banana"] // for...of文でプロパティの配列をループ for (const prop of props) { console.log(prop, fruits[prop]); } // > apple リンゴ // > banana バナナ
値の配列を取得する場合
const 値の配列 = Object.values(オブジェクト);
こちらは値を直接配列にします
const fruits = { apple: "リンゴ", banana: "バナナ" }; const values = Object.values(fruits); console.log(values); // > [ "リンゴ", "バナナ" ] // for...of文で値の配列をループ for (const value of values) { console.log(value); } // > リンゴ // > バナナ
プロパティと値のペアを取得する場合
オブジェクトのプロパティと値を両方ともループ処理に使用したい場合は
Object.entriesを使用します
const fruits = { apple: "リンゴ", banana: "バナナ" }; const entries = Object.entries(fruits); console.log(entries); // > [[apple, "リンゴ"], [banana, "バナナ"]] // for...of文でプロパティと値のペアの配列をループ for (const entry of entries) { console.log(entry[0], entry[1]); } // > apple リンゴ // > banana バナナ
break文、continue文、label文
break;
をループ中に記述すると現在のループそのものの処理を抜けることが出来ます
continue;
をループ中に記述すると現在のループの処理を抜けて次のループ処理に移すことが出来ます
label文
上記のキーワードと併用する形でループに名前をつけて対象のループのみを操作できるようになります
labelName: for(...){...[continue | break] labelName; }
主に複数のループ処理中のif文で使用しそうですね
switch文
JavaScriptにおけるswitch文の記述方法を備忘録として残しておく。
少し実例を交えて載せておきます
今回はHTMLのタグにID属性を#weathers
という属性名をターゲットに出力してみます
まずは配列でランダムに内容を取り出す変数を作成します。
const weathers = ["晴れ", "曇り", "雨", "雷", "雪", "曇のち晴れ"]; randomNumber = Math.floor(Math.random() * weathers.length); randomWeather = weathers[randomNumber]; document.getElementById("weather").textContent = "今日の天気は" + randomWeather + "です。";
Math.floor(Math.random() * weathers.length); この部分でランダムな数値を出しています。
これでランダムなお天気占いができました。
switch文で条件に合わせてコメントをする
weathermessage = document.getElementById("weathersMessage");
function ojaweathers(text) {
weathermessage.textContent = text;
}
まずテキストコンテントを引数で受け取れる関数を定義してしておきます。これを使用し、、
switch (randomWeather) { case "晴れ": ojaweathers("日傘を持っていったほうかいいかも"); break; //breakでループ文を抜ける case "曇り": ojaweathers("今日ははっきりしない空となりそう"); break; case "雨": ojaweathers("傘が手放せない一日になりそう"); break; case "雪": ojaweathers("今日は寒そうなのでコートを着ていきましょう"); break; default: ojaweathers("今日は家で引きこもりましょう、、"); }
こんな感じで書くとif文よりスマートに記述できるようになりました。
まとめ
今回は備忘録としてまだ理解が浅い、演算子と、JavaScriptならではのループ処理について書き記しておきました
お疲れさまでした
コメントをお待ちしております