カテゴリ「勉強」[2件]
JavaScriptを理解したいっ【変数編】の続きです。
前回はvarletconstについて学びましたので、今回は命名について勉強していきます。
命名規則
JavaScriptの命名での条件は以下のとおりです。
このあたりはC系言語でも同じ…$を命名で使える…のか…?
C系で$を命名に使ったのを見たことがなく、C#で試してみたら案の定エラーが出ました。JavaScriptだから使えるのかな……?
さて、変数、関数、classなど任意に名前を付けられるものは規則性が重要になってきます。
これは別に上記の条件さえ満たせば「こういう規則で名前をつけろ!」と厳密に決まっているものではありません。
個人サイト運営のなかでの命名は、自分だけが使うものであれば自分がわかればいいかなと思います。とはいえ「3日前の自分が書いたプログラムは他人が書いたと思え」と持論があるので(もしかしたら誰の言葉かもしれない)、今の自分がわかるからと横着して適当な命名をすると後々痛い目を見ます。尚、経験談。
未来の自分が分かるプログラムを書くために、命名規則を自分の中で定めてみよう!
可読性を重視
JavaScriptに限らずどの言語でも恐らく同じだとは思いますが、ある程度共通認識があります。
「名前からそれが何であるか分かりやすい」「長すぎず、省略しすぎない」「基本的に英単語を使う」は基本として知っていたのですが、記法について私の知ってるものと少し異なっていたのでそのあたりを深掘りしていきます。
なお、記法は複合語で使用するものです。
camelCase記法
camelCaseはキャメルケースと読みます。
camel=ラクダでラクダのコブのように「最初の単語の頭は小文字、次以降の単語の頭は大文字」というルールの書き方です。記法名のcamelCaseと同じ書き方ですね。
例えば「名前をセットする」目的のデータにcamelCaseを適応するとsetNameとなるような感じです。
恐らく一番よく使われる記法なのではないでしょうか?
C系言語に触れていたときは、変数名は基本的にこのcamelCase記法でした。
※開発現場やプログラマーによります。
Pascal記法
プログラム言語PascalにちなんでいるらしいこちらのPascal記法。Pascal=パスカルです。
単語の頭は大文字にする書き方で、先程のsetNameをPascal記法にするとSetNameになります。「JavaScript」「Perl」という単語もPascal記法ですね。
C系言語に触れていたときは、クラス名や関数名などをこの記法で書いていました。
全体の統一性から変数名をPascal記法で書いた時もありましたが、変数名か関数かの区別をつきやすくするため、変数名はcamelCase記法、関数・クラス名はPascal記法で統一するようになりました(私個人の話です!)
テンプレートに同梱しているJavaScriptを眺めてるとPascal記法を見かけないので、この記法はマイナーなのかな?と感想を抱いています。
アンダースコア記法
単語と単語の間に_(アンダースコア/アンダーバー)を挟むこの記法。
私は「snake case記法」と覚えていたので言語によって言い方が異なるのかも知れません。
setNameだとset_nameやSET_NAMEなどになります。
C系言語に触れていたときは、定数での命名は大文字+アンダースコア記法でした。
例えば#define WINDOW_WIDTH 1920とか#define WINDOW_HEIGHT 1080とか(C++ではconstではなく#defineで定数を設定することもできます)。この定数なら画面幅と画面高さを指定しているのが分かりますね。
JavaScriptだとconst WINDOW_WIDTH = 1920;やconst WINDOW_HEIGHT = 1080;となるでしょう。
参考にしている書籍だと「一般的に定数名で使用」とあるので、そのあたりは私の認識と共通していそうです。
JavaScriptライブラリjQueryを参考にしてみる
とってもお世話になっている便利ライブラリ「jQuery」の中身を見て、どんな命名規則なのか読み解いてみます。
変数名
jQuery v3.6.4 抜粋(48~71行目)
var arr = [];
var getProto = Object.getPrototypeOf;
var slice = arr.slice;
var flat = arr.flat ? function (array) {
return arr.flat.call(array);
} : function (array) {
return arr.concat.apply([], array);
};
var push = arr.push;
var indexOf = arr.indexOf;
var class2type = {};
var toString = class2type.toString;
var hasOwn = class2type.hasOwnProperty;
var fnToString = hasOwn.toString;
命名を見ていくので処理内容は省略します。
var arr = [];は配列定義ですね。arr=arrayの省略でしょう。
この省略は意味がわかるので使えそうです。
var getProto = Object.getPrototypeOf;はcamelCase記法なのがわかります。getは取得なのでProtoを取得した変数だと分かります。
var flat = arr.flat ? function (array) {
return arr.flat.call(array);
} : function (array) {
return arr.concat.apply([], array);
};これはif文を使わない条件分岐の書き方です。
arr.flatが真なら
function (array) {
return arr.flat.call(array);
} を実行し、arr.flatが偽なら
function (array) {
return arr.concat.apply([], array);
}を実行するというものです。C系でも使いますね。
条件分岐の中身が少ない場合はこの書き方がスマートなのでお気に入りです。
……脱線してしまった。
var indexOfvar toStringvar hasOwnvar fnToStringでもcamelCase記法ですね。
indexOfは「配列の何番目か」、toStringは「文字列に変換」、hasOwnは「自身を持つかのフラグ」、fnToStringは「関数を文字列に変換」、といったところかなと思います。
indexOfやtoStringはC#でも使ったことがあるのですんなり意味を読み取れました。
JavaScriptは関数を示すときfunctionを記述するので、functionを省略してfnということでしょう。この省略の仕方も使えそうです。
ちなみにC#やC++は戻り値なしの関数を記述するときはvoidから始まります。
JavaScriptは戻り値があろうがなかろうがfunctionで指定できますが、C#やC++では戻り値がある関数を書きたいときは戻り値と同じデータ型で書き始める必要があります。
そう考えるとfunction万能すぎでは……?
var class2typeは「classをtypeで」といったところでしょうか。
「数字を文字列で」などのような変換系の命名ではnumberToStringではなくnumber2stringのように「2」を使って表すことがあります。number2stringのnumberやStringもnumやstrで省略しても分かりそうなのでnum2strでも良さそうです。
camelCaseでいくならclass2Typeでは?と思ったのですが、読みやすさ重視でclass2typeなのかもしれません。変換系のデータが他になかったので確認できませんでした。まあ読みやすいのでclass2typeがいいですね。
var toStringがvar 2stringでないのは変数名の頭に数字は使えないからでしょう。
以上から、
だと分かりました。
ここまでやっておいてあれですが、「そもそもJavaScriptにある変数見れば早いのでは」と気づきました。
ということで事項関数名はJavaScriptの方を見ていきます。
関数名
JavaScriptの関数についてはなかなか特殊な書き方をすることがあるので関数についても勉強したいところ……。
document.getElementById()やdocument.querySelector()からみても分かる通り、JavaScriptとして関数名はcamelCase記法の模様。
一応jQueryの中身も見てみたのですが、JavaScriptにラップ(元の機能やデータに機能やデータを追加したり削除したりして、同じ名前でも元とは別の内容で処理すること)してる形がほとんどっぽかったので省略します。
最後に
これまでを踏まえ、「変数名」「関数名」はcamelCase記法で今後は記述を心がけていこうと思います。
参考にした書籍によると定数をアンダースコア記法のが一般だそうです。C#やC++と同じですね。
お借りしたり作っていただいたりしたテンプレートに同梱されているJavaScriptファイルを見ると、基本的にcamelCase記法で統一されているみたいでした。テンプレート利用のサイトで使うJavaScriptはひとまずそちらに合わせていきます。
ただまあなるべくたくさん見て触れたほうが自分のためになるはずなので、いつもお世話になっているサイト様以外の、別のサイト様のテンプレートも勉強として見漁る予定です。
とりあえずまずは数年積み本にしてるリーダブルコードをちゃんと読みます!
目指せ!読みやすいコード!!
関連記事
JavaScriptを理解したいっ【変数編】
参考
改訂新版JavaScript本格入門モダンスタイルによる基礎から現場での応用まで
※私が参考にしたのは2019年発行のものですが、最新版があるのでご購入の際は最新版(改訂3版JavaScript本格入門
~モダンスタイルによる基礎から現場での応用まで)が良いかと思います。
前回はvarletconstについて学びましたので、今回は命名について勉強していきます。
命名規則
JavaScriptの命名での条件は以下のとおりです。
- 1文字目は英字、_(アンダースコア)、$(ドル記号)のいずれかであること
- 2文字目以降は1文字目で使える文字、もしくは数字のいずれかであること
- 変数名に含まれる英字の大文字・小文字は区別される
- JavaScriptで意味を持つ予約語ではないこと
このあたりはC系言語でも同じ…$を命名で使える…のか…?
C系で$を命名に使ったのを見たことがなく、C#で試してみたら案の定エラーが出ました。JavaScriptだから使えるのかな……?
さて、変数、関数、classなど任意に名前を付けられるものは規則性が重要になってきます。
これは別に上記の条件さえ満たせば「こういう規則で名前をつけろ!」と厳密に決まっているものではありません。
個人サイト運営のなかでの命名は、自分だけが使うものであれば自分がわかればいいかなと思います。とはいえ「3日前の自分が書いたプログラムは他人が書いたと思え」と持論があるので(もしかしたら誰の言葉かもしれない)、今の自分がわかるからと横着して適当な命名をすると後々痛い目を見ます。尚、経験談。
未来の自分が分かるプログラムを書くために、命名規則を自分の中で定めてみよう!
可読性を重視
JavaScriptに限らずどの言語でも恐らく同じだとは思いますが、ある程度共通認識があります。
- 記法を統一する
- 名前からそれが何であるか分かりやすくする
- 長すぎず、省略しすぎない
- 基本的に英単語を使う
「名前からそれが何であるか分かりやすい」「長すぎず、省略しすぎない」「基本的に英単語を使う」は基本として知っていたのですが、記法について私の知ってるものと少し異なっていたのでそのあたりを深掘りしていきます。
なお、記法は複合語で使用するものです。
camelCase記法
camelCaseはキャメルケースと読みます。
camel=ラクダでラクダのコブのように「最初の単語の頭は小文字、次以降の単語の頭は大文字」というルールの書き方です。記法名のcamelCaseと同じ書き方ですね。
例えば「名前をセットする」目的のデータにcamelCaseを適応するとsetNameとなるような感じです。
恐らく一番よく使われる記法なのではないでしょうか?
C系言語に触れていたときは、変数名は基本的にこのcamelCase記法でした。
※開発現場やプログラマーによります。
Pascal記法
プログラム言語PascalにちなんでいるらしいこちらのPascal記法。Pascal=パスカルです。
単語の頭は大文字にする書き方で、先程のsetNameをPascal記法にするとSetNameになります。「JavaScript」「Perl」という単語もPascal記法ですね。
C系言語に触れていたときは、クラス名や関数名などをこの記法で書いていました。
全体の統一性から変数名をPascal記法で書いた時もありましたが、変数名か関数かの区別をつきやすくするため、変数名はcamelCase記法、関数・クラス名はPascal記法で統一するようになりました(私個人の話です!)
テンプレートに同梱しているJavaScriptを眺めてるとPascal記法を見かけないので、この記法はマイナーなのかな?と感想を抱いています。
アンダースコア記法
単語と単語の間に_(アンダースコア/アンダーバー)を挟むこの記法。
私は「snake case記法」と覚えていたので言語によって言い方が異なるのかも知れません。
setNameだとset_nameやSET_NAMEなどになります。
C系言語に触れていたときは、定数での命名は大文字+アンダースコア記法でした。
例えば#define WINDOW_WIDTH 1920とか#define WINDOW_HEIGHT 1080とか(C++ではconstではなく#defineで定数を設定することもできます)。この定数なら画面幅と画面高さを指定しているのが分かりますね。
JavaScriptだとconst WINDOW_WIDTH = 1920;やconst WINDOW_HEIGHT = 1080;となるでしょう。
参考にしている書籍だと「一般的に定数名で使用」とあるので、そのあたりは私の認識と共通していそうです。
JavaScriptライブラリjQueryを参考にしてみる
とってもお世話になっている便利ライブラリ「jQuery」の中身を見て、どんな命名規則なのか読み解いてみます。
変数名
jQuery v3.6.4 抜粋(48~71行目)
var arr = [];
var getProto = Object.getPrototypeOf;
var slice = arr.slice;
var flat = arr.flat ? function (array) {
return arr.flat.call(array);
} : function (array) {
return arr.concat.apply([], array);
};
var push = arr.push;
var indexOf = arr.indexOf;
var class2type = {};
var toString = class2type.toString;
var hasOwn = class2type.hasOwnProperty;
var fnToString = hasOwn.toString;
命名を見ていくので処理内容は省略します。
var arr = [];は配列定義ですね。arr=arrayの省略でしょう。
この省略は意味がわかるので使えそうです。
var getProto = Object.getPrototypeOf;はcamelCase記法なのがわかります。getは取得なのでProtoを取得した変数だと分かります。
var flat = arr.flat ? function (array) {
return arr.flat.call(array);
} : function (array) {
return arr.concat.apply([], array);
};これはif文を使わない条件分岐の書き方です。
arr.flatが真なら
function (array) {
return arr.flat.call(array);
} を実行し、arr.flatが偽なら
function (array) {
return arr.concat.apply([], array);
}を実行するというものです。C系でも使いますね。
条件分岐の中身が少ない場合はこの書き方がスマートなのでお気に入りです。
……脱線してしまった。
var indexOfvar toStringvar hasOwnvar fnToStringでもcamelCase記法ですね。
indexOfは「配列の何番目か」、toStringは「文字列に変換」、hasOwnは「自身を持つかのフラグ」、fnToStringは「関数を文字列に変換」、といったところかなと思います。
indexOfやtoStringはC#でも使ったことがあるのですんなり意味を読み取れました。
JavaScriptは関数を示すときfunctionを記述するので、functionを省略してfnということでしょう。この省略の仕方も使えそうです。
ちなみにC#やC++は戻り値なしの関数を記述するときはvoidから始まります。
JavaScriptは戻り値があろうがなかろうがfunctionで指定できますが、C#やC++では戻り値がある関数を書きたいときは戻り値と同じデータ型で書き始める必要があります。
そう考えるとfunction万能すぎでは……?
var class2typeは「classをtypeで」といったところでしょうか。
「数字を文字列で」などのような変換系の命名ではnumberToStringではなくnumber2stringのように「2」を使って表すことがあります。number2stringのnumberやStringもnumやstrで省略しても分かりそうなのでnum2strでも良さそうです。
camelCaseでいくならclass2Typeでは?と思ったのですが、読みやすさ重視でclass2typeなのかもしれません。変換系のデータが他になかったので確認できませんでした。まあ読みやすいのでclass2typeがいいですね。
var toStringがvar 2stringでないのは変数名の頭に数字は使えないからでしょう。
以上から、
- 変数名は基本的にcamelCase記法
- array、functionなどはarrやfnと省略
- 変換系は「2」で挟みすべて小文字でcamelCase記法から外れる
だと分かりました。
ここまでやっておいてあれですが、「そもそもJavaScriptにある変数見れば早いのでは」と気づきました。
ということで事項関数名はJavaScriptの方を見ていきます。
関数名
JavaScriptの関数についてはなかなか特殊な書き方をすることがあるので関数についても勉強したいところ……。
document.getElementById()やdocument.querySelector()からみても分かる通り、JavaScriptとして関数名はcamelCase記法の模様。
一応jQueryの中身も見てみたのですが、JavaScriptにラップ(元の機能やデータに機能やデータを追加したり削除したりして、同じ名前でも元とは別の内容で処理すること)してる形がほとんどっぽかったので省略します。
最後に
これまでを踏まえ、「変数名」「関数名」はcamelCase記法で今後は記述を心がけていこうと思います。
参考にした書籍によると定数をアンダースコア記法のが一般だそうです。C#やC++と同じですね。
お借りしたり作っていただいたりしたテンプレートに同梱されているJavaScriptファイルを見ると、基本的にcamelCase記法で統一されているみたいでした。テンプレート利用のサイトで使うJavaScriptはひとまずそちらに合わせていきます。
ただまあなるべくたくさん見て触れたほうが自分のためになるはずなので、いつもお世話になっているサイト様以外の、別のサイト様のテンプレートも勉強として見漁る予定です。
とりあえずまずは数年積み本にしてるリーダブルコードをちゃんと読みます!
目指せ!読みやすいコード!!
関連記事
JavaScriptを理解したいっ【変数編】
参考
改訂新版JavaScript本格入門モダンスタイルによる基礎から現場での応用まで
※私が参考にしたのは2019年発行のものですが、最新版があるのでご購入の際は最新版(改訂3版JavaScript本格入門
~モダンスタイルによる基礎から現場での応用まで)が良いかと思います。
C#畑にいたころ、「C#とJavaScriptは似てる」というような話をたびたび聞きました。
有名なゲームエンジンUnityがかつてサポートしていた言語がC#とJavaScriptであったこと(※現在UnityはC#のみです)もあり、C#とJavaScriptは似てると先入観のまま触れるようになりました。
初めて見たJavaScriptのソースがjQuery使用のものだったので、
「全然違うじゃん!!なんだこの表記!!」
とたじろいだ記憶があります。
jQuery特有の記載方法であり、JavaScriptがすべてあの書き方ではないと今なら分かります。
実際JavaScriptに触れてみて
「ある程度基本的な部分はどの言語も恐らく同じ。配列の扱いは確かに似ているかもしれない」
と感想を抱きました。
とはいえ、言語が違えば”常識”も違う。
雰囲気で使っているあれこれを、C系言語と比較しながら今一度きちんと勉強して理解するぞ!おー!!
※記事が長くなったので命名については分けます。
変数宣言
JavaScriptで変数宣言するとき
varletconst
の3種類の命令から始まります。
違いをそこまで理解できていなかったので、まずはここからお勉強。
var
C#にも型推論のvarがあるので同じものだと思ってました。C++だとauto。
JavaScriptのvarもおおよそ挙動は同じ。
ただし、なんとこやつグローバルで宣言でき、初期化しなくてもエラーにならず、しかも同じ名前で何度も宣言できて、スコープ内で宣言したものを外でも使えるのである!
分かりますか奥様!この驚きたるや。
例えばC#で以下のように記述してみる。
エントリポイント(ソースが実行される開始点)が必要な関係上class内に入れている
class Program
{
var test;
static void Main()
{
var test2;
var test3 = 0;
var test3 = 2;
var test4 = 0;
test4 = 4;
var test5 = 0;
for (int i = 0; i < 10; i++)
{
test5++;
}
var test6 = 0;
Console.WriteLine("test6は" + test6 + "です。");
}
}
上記だと、test4~test6以外はエラーになる。
これをJavaScriptで書き直してみよう。
classは一旦おいておく
var test;
function Main()
{
var test2;
var test3 = 0;
var test3 = 2;
var test4 = 0;
test4 = 4;
var test5 = 0;
for (var i = 0; i < 10 ; i++) {
test5++;
}
var test6 = 0;
console.log("test6は" + test6 + "です。");
}
JavaScriptはなんとエラーにならない!!
しゅごい……。
この挙動はJavaScript特有のものらしく、「巻き上げ」と呼ぶそうです。脳内でへえボタン連打しました。へえボタン…分かるかな…ハハ。
とはいえ、C#扱っていた頃はデータ型きっちり書きたいマンでvarを使う習慣がさほどなかったので、JavaScriptで記述する際にintを使おうとしてエラって「intがない…だと…?」と困惑した記憶があります笑
varの再宣言ができて便利だなと思う一方、
と記事を見つけたので肝に銘じます。
スコープ内で宣言したものを外でも使えるのスコープとは、for(条件文){...}やif(条件文){...}など{ }で囲まれた部分のことを言います。
これがね…実に気持ち悪い面白い動きなんですよね。
C#でスコープ内で宣言した変数をスコープ外で使おうとするとエラーが出ます。
JavaSciptさんはなんとえらーがでないんですねぇ。
宣言以降も使えるというのはなんやかんや使いやすいんだろうなとは思います。ちょっと私はまだ慣れないけれど、必要になったところから宣言できるのは、「この宣言した変数どこから使い始めてるんだ?」となるよりソースの可読性が高くなると思えばいいものなのかもしれません。
let
Let It Go が思い浮かぶほど馴染みないものでした。なんやこれ。
なので実はあんま使ってなかった。これからきっと使いこなせるはず…!
varと使い方が似ているletの特徴は同じ名前の変数を作れない、ブロックスコープを意識していることです。
前項varで分かる通り、私が過去触れた言語(C、C#、C++など)は同じ名前の宣言ができません(別同士のブロックスコープであれば名前が同じでも可。ブロックスコープについては後ほど)。
なので私からするとletのほうが馴染みがあるものでした。びっくり!
ただまあ、例えば「タグ内のテキストを取得したい」とかだと変数名をtextとかにするのが分かりやすくて楽だし何かと多用してしまいそうなので、jsファイル内に1つだけの変数にしたいときに使うのがいいのかな?とか思いました。
…いや、下手なこと言っちゃいけないな…ううむ…
2つ目のブロックスコープを意識しているに触れていきます。
「ブロックスコープ?」と初めは疑問でしたが、C系時代は「当たり前すぎて一周回って意識しない」感じのものでした。
ブロックスコープとは{}で囲まれた領域内のことを指します。
昔はブロックレベルはなかったそうですが、ES2015(2015年に標準化されたJavaSciptの規格ECMASCriptのこと。6版であるためES6と呼ばれていたらしい)で新しくブロックレベルが追加されました。letが使えるようになったのもこのときです。
varではfor文やif文内で宣言した変数を外でも使えましたが、letは使えない…個人的に挙動としてはこちらのほうがしっくり来ます。
letもvarもデータの上書きが可能なので、どう使うのが良いかいろんなプログラム見てもう少し勉強が必要そうです。
const
これはC#やC++にあるのと同じものでした。
データ型の宣言がない点では違和感を覚えますが、JavaScriptはそういうものなんですね。
constは定数です。定数とは「値が変わらないもの」のことです。
サイトで使うJavaScriptはあまり数字が出てこない印象があるのですが、ゲームプログラムだと数字がたくさん出てきます。パラメーターあたりなんかは数字祭りですね。
プログラムを打つ中で数字を扱うとき、原則として数字の意味を明確にしなければなりません。パッと見てなにを表すかわからない数字のことをマジックナンバーといいます。魔法の数字、でもすっごく嫌われる数字です。初期化で使う0は例外だとは思いますが。
例えば、jQueryを使い「速度500ミリ秒(0.5秒)のスクロールアニメーションを実装しよう」とします。
当サイトでのやり方だと
$('a[href^="#"]').click(function () {
let href = $(this).attr("href");
let target = $(href == "#" || href == "" ? "html" : href);
let position = target.offset().top;
$("body,html").animate({ scrollTop: position }, 500, "swing");
return false;
});
になるわけですが、上記だと「500」の数字がマジックナンバーです。
「なんの処理か分かるし500が何を意味してるか分かるから別にこのままでもいいんじゃ?」
と思うでしょう。自分ひとりで好きなようにやっているのであればそれでもかまわないと思います。
ただ、他に使う人がいる場合はたとえ相手が意味をわかったとしても定数化しておくべきでしょう。
上記のコードであれば
$('a[href^="#"]').click(function () {
const animSpeed = 500;
let href = $(this).attr("href");
let target = $(href == "#" || href == "" ? "html" : href);
let position = target.offset().top;
$("body,html").animate({ scrollTop: position }, animSpeed, "swing");
return false;
});
と言った感じにするのがいいかな?と思います。
横着してclickイベント内でconst宣言していますが、もし全体的によく使うものであればconstの宣言はファイルの一番最初にやるのが定石かなと思います。(C系で語ってるけどJavaScriptもそうだよね…?)
constで宣言されたものはデータの書き換えができません。これがvarやletとの大きな違いでしょう。
C系で使うときはデータ型が必要なのでconst float TAX = 1.1;みたいな使い方ですが、JavaScript はデータ型宣言がなくとも使えるので数字以外にタグやセレクタでも使えますね。(例:const TAX = document.getElementById("TAX");)
何度も使うタグはconstで定義しておくと楽だと思います。
最後に
個人サイトを作った当初はなんとな~く「動けばいいや」と開設や運営に重きをおいていました。今ではJavaScriptで実装したいことがあればある程度自力で書けるようになったと思います。
そんな今だからこそ、基礎的な部分を学び直せば理解が深まるのではと(諸事情で買った)本を開きました。
まだまだ序盤しか読めていませんが、今の私にはちょうどよく分かりやすいので本で学んだことを自分の考えを添えて記事にしていこうと思います。
JavaScript勉強の旅は始まったばかりであるっ!
関連記事
JavaScriptを理解したいっ【命名編】
参考
JavaScriptでvarが非推奨な理由を整理してみた
改訂新版JavaScript本格入門モダンスタイルによる基礎から現場での応用まで
※私が参考にしたのは2019年発行のものですが、最新版があるのでご購入の際は最新版(改訂3版JavaScript本格入門
~モダンスタイルによる基礎から現場での応用まで)が良いかと思います。
有名なゲームエンジンUnityがかつてサポートしていた言語がC#とJavaScriptであったこと(※現在UnityはC#のみです)もあり、C#とJavaScriptは似てると先入観のまま触れるようになりました。
初めて見たJavaScriptのソースがjQuery使用のものだったので、
「全然違うじゃん!!なんだこの表記!!」
とたじろいだ記憶があります。
jQuery特有の記載方法であり、JavaScriptがすべてあの書き方ではないと今なら分かります。
実際JavaScriptに触れてみて
「ある程度基本的な部分はどの言語も恐らく同じ。配列の扱いは確かに似ているかもしれない」
と感想を抱きました。
とはいえ、言語が違えば”常識”も違う。
雰囲気で使っているあれこれを、C系言語と比較しながら今一度きちんと勉強して理解するぞ!おー!!
※記事が長くなったので命名については分けます。
変数宣言
JavaScriptで変数宣言するとき
varletconst
の3種類の命令から始まります。
違いをそこまで理解できていなかったので、まずはここからお勉強。
var
C#にも型推論のvarがあるので同じものだと思ってました。C++だとauto。
JavaScriptのvarもおおよそ挙動は同じ。
ただし、なんとこやつグローバルで宣言でき、初期化しなくてもエラーにならず、しかも同じ名前で何度も宣言できて、スコープ内で宣言したものを外でも使えるのである!
分かりますか奥様!この驚きたるや。
例えばC#で以下のように記述してみる。
エントリポイント(ソースが実行される開始点)が必要な関係上class内に入れている
class Program
{
var test;
static void Main()
{
var test2;
var test3 = 0;
var test3 = 2;
var test4 = 0;
test4 = 4;
var test5 = 0;
for (int i = 0; i < 10; i++)
{
test5++;
}
var test6 = 0;
Console.WriteLine("test6は" + test6 + "です。");
}
}
上記だと、test4~test6以外はエラーになる。
これをJavaScriptで書き直してみよう。
classは一旦おいておく
var test;
function Main()
{
var test2;
var test3 = 0;
var test3 = 2;
var test4 = 0;
test4 = 4;
var test5 = 0;
for (var i = 0; i < 10 ; i++) {
test5++;
}
var test6 = 0;
console.log("test6は" + test6 + "です。");
}
JavaScriptはなんとエラーにならない!!
しゅごい……。
この挙動はJavaScript特有のものらしく、「巻き上げ」と呼ぶそうです。脳内でへえボタン連打しました。へえボタン…分かるかな…ハハ。
とはいえ、C#扱っていた頃はデータ型きっちり書きたいマンでvarを使う習慣がさほどなかったので、JavaScriptで記述する際にintを使おうとしてエラって「intがない…だと…?」と困惑した記憶があります笑
varの再宣言ができて便利だなと思う一方、
変数を簡単に書き換えられてしまうと、意図しないバグが発生する
letやconstに比べて、varは巻き上げ時のバグを生み出しやすい
と記事を見つけたので肝に銘じます。
スコープ内で宣言したものを外でも使えるのスコープとは、for(条件文){...}やif(条件文){...}など{ }で囲まれた部分のことを言います。
これがね…実に
C#でスコープ内で宣言した変数をスコープ外で使おうとするとエラーが出ます。
JavaSciptさんはなんとえらーがでないんですねぇ。
宣言以降も使えるというのはなんやかんや使いやすいんだろうなとは思います。ちょっと私はまだ慣れないけれど、必要になったところから宣言できるのは、「この宣言した変数どこから使い始めてるんだ?」となるよりソースの可読性が高くなると思えばいいものなのかもしれません。
let
Let It Go が思い浮かぶほど馴染みないものでした。なんやこれ。
なので実はあんま使ってなかった。これからきっと使いこなせるはず…!
varと使い方が似ているletの特徴は同じ名前の変数を作れない、ブロックスコープを意識していることです。
前項varで分かる通り、私が過去触れた言語(C、C#、C++など)は同じ名前の宣言ができません(別同士のブロックスコープであれば名前が同じでも可。ブロックスコープについては後ほど)。
なので私からするとletのほうが馴染みがあるものでした。びっくり!
ただまあ、例えば「タグ内のテキストを取得したい」とかだと変数名をtextとかにするのが分かりやすくて楽だし何かと多用してしまいそうなので、jsファイル内に1つだけの変数にしたいときに使うのがいいのかな?とか思いました。
…いや、下手なこと言っちゃいけないな…ううむ…
2つ目のブロックスコープを意識しているに触れていきます。
「ブロックスコープ?」と初めは疑問でしたが、C系時代は「当たり前すぎて一周回って意識しない」感じのものでした。
ブロックスコープとは{}で囲まれた領域内のことを指します。
昔はブロックレベルはなかったそうですが、ES2015(2015年に標準化されたJavaSciptの規格ECMASCriptのこと。6版であるためES6と呼ばれていたらしい)で新しくブロックレベルが追加されました。letが使えるようになったのもこのときです。
varではfor文やif文内で宣言した変数を外でも使えましたが、letは使えない…個人的に挙動としてはこちらのほうがしっくり来ます。
letもvarもデータの上書きが可能なので、どう使うのが良いかいろんなプログラム見てもう少し勉強が必要そうです。
const
これはC#やC++にあるのと同じものでした。
データ型の宣言がない点では違和感を覚えますが、JavaScriptはそういうものなんですね。
constは定数です。定数とは「値が変わらないもの」のことです。
サイトで使うJavaScriptはあまり数字が出てこない印象があるのですが、ゲームプログラムだと数字がたくさん出てきます。パラメーターあたりなんかは数字祭りですね。
プログラムを打つ中で数字を扱うとき、原則として数字の意味を明確にしなければなりません。パッと見てなにを表すかわからない数字のことをマジックナンバーといいます。魔法の数字、でもすっごく嫌われる数字です。初期化で使う0は例外だとは思いますが。
例えば、jQueryを使い「速度500ミリ秒(0.5秒)のスクロールアニメーションを実装しよう」とします。
当サイトでのやり方だと
$('a[href^="#"]').click(function () {
let href = $(this).attr("href");
let target = $(href == "#" || href == "" ? "html" : href);
let position = target.offset().top;
$("body,html").animate({ scrollTop: position }, 500, "swing");
return false;
});
になるわけですが、上記だと「500」の数字がマジックナンバーです。
「なんの処理か分かるし500が何を意味してるか分かるから別にこのままでもいいんじゃ?」
と思うでしょう。自分ひとりで好きなようにやっているのであればそれでもかまわないと思います。
ただ、他に使う人がいる場合はたとえ相手が意味をわかったとしても定数化しておくべきでしょう。
上記のコードであれば
$('a[href^="#"]').click(function () {
const animSpeed = 500;
let href = $(this).attr("href");
let target = $(href == "#" || href == "" ? "html" : href);
let position = target.offset().top;
$("body,html").animate({ scrollTop: position }, animSpeed, "swing");
return false;
});
と言った感じにするのがいいかな?と思います。
横着してclickイベント内でconst宣言していますが、もし全体的によく使うものであればconstの宣言はファイルの一番最初にやるのが定石かなと思います。(C系で語ってるけどJavaScriptもそうだよね…?)
constで宣言されたものはデータの書き換えができません。これがvarやletとの大きな違いでしょう。
C系で使うときはデータ型が必要なのでconst float TAX = 1.1;みたいな使い方ですが、JavaScript はデータ型宣言がなくとも使えるので数字以外にタグやセレクタでも使えますね。(例:const TAX = document.getElementById("TAX");)
何度も使うタグはconstで定義しておくと楽だと思います。
最後に
個人サイトを作った当初はなんとな~く「動けばいいや」と開設や運営に重きをおいていました。今ではJavaScriptで実装したいことがあればある程度自力で書けるようになったと思います。
そんな今だからこそ、基礎的な部分を学び直せば理解が深まるのではと(諸事情で買った)本を開きました。
まだまだ序盤しか読めていませんが、今の私にはちょうどよく分かりやすいので本で学んだことを自分の考えを添えて記事にしていこうと思います。
JavaScript勉強の旅は始まったばかりであるっ!
関連記事
JavaScriptを理解したいっ【命名編】
参考
JavaScriptでvarが非推奨な理由を整理してみた
改訂新版JavaScript本格入門モダンスタイルによる基礎から現場での応用まで
※私が参考にしたのは2019年発行のものですが、最新版があるのでご購入の際は最新版(改訂3版JavaScript本格入門
~モダンスタイルによる基礎から現場での応用まで)が良いかと思います。