オイオイオイ書くわアイツ

ほうクソブログですか……たいしたものですね

C 言語しか触ったことない人向け JavaScript 入門

概要

  • 詳しいドキュメントはここ -> JavaScript | MDN
  • console.log(hoge) を使え
  • オブジェクトは便利
  • ファーストクラス関数を使いこなせるようになれ

はじめに

電子情報工学科の学生実験として、情報可視化実験というものが行われています。大量なデータ(ビッグデータ)を扱う上で、そこから得られる情報を可視化する技術の基礎を学ぶための実験です。この実験においては、情報可視化システムを自ら立案し、JavaScript のライブラリである D3.js を用いて、ツーマンセルでGithub上でチーム開発を行うことが学生に求められています。情報可視化技術と JavaScript による開発技術、およびチーム開発の作法はいずれも重要なものですが、実験中に全てを手取り足取り教えるというわけにもいかないのが実情です。(詳しくは 4 ターム制になったせいで実験の日数が減ったことについて調べてみて下さい。)そこで本記事では、実験で求められる要素の内、 JavaScript による開発ついての基本的な事項について紹介しようと思います。

本記事では「プログラミング言語は必修講義でやった C くらいしか知らないよー」という人向けに JavaScript の基本的な事項について紹介します。D3.js に関係しそうな事柄についてはおおよそ説明していると思うので、「一体何をしているのか全然わからないぞ」ということがあったら読んでほしいです。もちろん、直接 TA に聞いてくれても大丈夫です。また、本記事では JavaScript の構文についてのみ説明しています。ビルトインファンクションや DOM の操作など、もう一歩進んだ部分についての記事は(今年度とは限らない)後日にまた作成するかもしれません。この記事が実験の円滑な進行の一助となれば幸いです。

JavaScript の構文

JavaScript (JS) は軽量で、インタプリタ型の、第一級関数を備えたプログラミング言語です。Web ページでよく使用されるスクリプト言語として知られ、node.js や Apache CouchDB といった多くの非ブラウザ環境においても使用されています。 JavaScript は プロトタイプベースで、動的型付けを持ち、そしてオブジェクト指向、命令形、そして関数プログラミングといったスタイルをサポートするマルチパラダイムスクリプト言語です。詳しくは JavaScript についてをお読みください。

https://developer.mozilla.org/ja/docs/Web/JavaScript より

詳しくなく、かつ正確でない説明をここでします。とりあえずこれを読めば講義中に書くコードが何をしているのかがわかるかもしれないです。大体は C と同じなので、ざっと眺めるだけで大丈夫ですよ!詳しい説明が読みたい人は上の引用元から mozilla のサイトに行きましょう。

console.log

最初に覚えてほしいのは console.log です。 print みたいなものです。 console.logprint 、覚えましたね。 学科の講義ではまだ C 言語しか触ったことがないよ、という人もいるかもしれないので、そういう人たち向けに言っておくと、 printf のもう少しガバガバなものです。 ”なんか気になるもの”(これは変数や、文字列や、後述するオブジェクト、とにかくなんでも!)を渡してあげるとブラウザのコンソールで中身が見れる優れものです。これを使って実際のコーディングもこの記事の説明も進めていきましょう。

変数の宣言

JavaScript では var というキーワードで変数を宣言します。宣言と同時に値を初期化することもできます。以下のコードに例を示します。

var a;
var b = "hoge";

JavaScript ではまた変数に値を再代入することもできます。ガバガバなので、異なる型の値を再代入することも可能です。以下のコードに例を示します。

a = "hoge";
console.log(a);
// hoge
a = 1;
console.log(a);
// 1

また、値が代入されていない変数は次のように undefined 型になります。 undefined 型は後述するように少し奇妙な振る舞いを見せるので、気をつけて下さい。以下のコードに例を示します。

var c;
console.log(c);
// undefined

テキストエディタとしてatomを使っている方は、「log」とうつと「console.log」と保管されます。いちいち打つのは結構面倒臭いと思うので、こういった便利なスニペットについても覚えておくと良いでしょう。

コメント

今何気なく使いましたが、 JavaScript では以下の2つのコメントの形式があります。

// コメント
/*
これも
コメント
*/

C言語と同じなのですんなり受け入れられると思います。チーム開発する際やTAがコードを採点する際にはコメントがないと伝わりづらいこともあるので、わかりづらそうな部分については積極的にコメントを書くようにしましょう。 ちなみにatomでは、行を選択した状態で ctrl + / をするとコメントアウトとアンコメントができます。デバッグ時によく使うテクニックなので、この機能も積極的に使ってみてください。

演算子

大体 C とおんなじ! +-*/% なんかの基本的な演算子を使えます。+=-= なんかの復号演算子もあります。以下の2つが同じ意味になる感じの演算子です。

x += 10;
x = x + 5;

++-- でインクリメント・デクリメントもできます。+ で C では難しかった文字列の結合もできます。更に、数字なんかと混ぜて綴命の錬金術師のような結合もできます。

var a = "takatsuki" + "yayoi";
console.log(a);
// takatsukiyayoi
var b = "takatsuki" + 841;
console.log(b);
// takatsuki841;
var c = "takatsuki" + 800 + 40 + 1;
console.log(c);
// takatsuki800401
var d = "takatsuki" + (800 + 40 + 1);
console.log(d);
// takatsuki841

比較

比較演算子についての話題は上の「演算子」の節に入れるべきかとも思いましたが、ちょっと独特なものなので節をわけました。「変数」の節でも触れましたが、undefined 型の存在もあいまってわかりにくい部分ですので、頑張ってください。 JavaScript においては == 演算子=== 演算子を用いて比較を行うことができます。この内 == 演算子のほうは、 MDN には「これは時に面白い結果を返します」と記載があるのですが、まったくおもしろくない、不愉快な結果を与えることがあるので、注意をしておいてほしいなと思います。 詳細については今から述べますが、結論から言うと === を使って下さい。 == は比較をするときに、両辺の値の型が異なると型強制を(つまり“よしなに”してくれようと)します。具体的には、以下のようなことがおこります。

var a = 841 == "841";
console.log(a);
// true
var b = 1 == true;
console.log(b);
// true
var c = null == undefined;
console.log(c);
// true

ワォ! 841"841" は同一、そうだね、僕の気持ちとしてもそうだよ!でも、実際にプログラミングをするときには、これは結構困りものです。JavaScript はただでさえ変数の型をコロコロ変えることができるのに、比較するときまで“なあなあ”で済ますのはあまりよろしくありません。(もちろん、変数の型を変えないようにすることもできますが、それはちょっと今は置いておきます。) === 演算子による比較は型について厳格なので、こっちのほうが安心です。

console.log(typeof(null));
// object
console.log(typeof(undefined));
// undefined
console.log(null === undefined);
// false

ここらへんの話は Python==is の話にも似ているので、ちょっと覚えておくと良いかもしれません。(似ているだけで別の話です。念のため。)

制御構造

ifwhiledo whileforswitch などが大体 C 言語と同じような感じで使えます。

if (score < 60){
    return "不可";
} else {
    return "優上";
}

こんな感じです。(実際の大学には不可と優上以外にも幾つかの成績区分が存在します。) 三項演算子Python のようなギョッとする形ではなく、普通のやつが使えます。

var grade = (score < 60) ? "不可" : "優上";

オブジェクト

JavaScript におけるオブジェクトはキーと値のペアをひとまとまりにしたものです。これはPython の辞書型、あるいは Ruby のハッシュ、あるいはその他の言語のなんらかのそういう代物と似ています。 以下のようにして、あるキーに対する値を登録することができます。

var hoge =
    { key1: "value1"
    , key2: "value2"
    };

この値は、以下のようにして高速に呼び出すことができます。

console.log(hoge.key1);
// value1
console.log(hoge["key2"]);
// value2

新しいペアを追加するときには、呼び出すときと同じようにします。

hoge.pa = "mi";
hoge["mo"] = "piyo";
console.log(hoge);
// Object {key1: "value1", key2: "value2", pa: "mi", mo: "piyo"}

オブジェクトの生成方法には他にもいくつかの方法がありますが、基本的にはこの方法が好まれるようです。キーには様々な値を対応させることができます。例えば、数値・文字列・配列・オブジェクト・関数などです。(関数については次節参照。)以下の例を見ても、オブジェクトの便利さが分かってもらえると思います。

var Moltres =
    { lv: 51
    , moves:
        [{name: "にらみつける", pp: 30}
        ,{name: "つつく", pp: 35}
        ,{name: "ほのおのうず", pp: 15}
        ]
    , versionUp:
        function(){
            this.moves[0] = {name: "かえんほうしゃ", pp: 15};
        }
    };
console.log(Moltres.lv);
// 51
console.log(Moltres.moves);
// [Object, Object, Object]
console.log(Moltres.moves[0]);
// Object {name: "にらみつける", pp: 30}
console.log(Moltres.moves[0].name);
// にらみつける
Moltres.versionUp();
console.log(Moltres.moves[0].name);
// かえんほうしゃ

オブジェクトの中にオブジェクトの配列が……となると、ちょっとアクセスしにくい感じもしますが、データを格納・利用しやすいということが伝わったかなと思います。特に、関数もオブジェクトに格納できるよ、というのは中々便利です。 ここで、this というキーワードが出てきましたが、これは現在のオブジェクトを参照します。すなわち、今回は Moltres オブジェクトを指しています。this の意味するものは文脈によるので、これ以外にどのような使われ方をしてどのように働くかということに関しては、各自必要なときに調べてみてくださいね!!

関数

C 言語と JavaScript を大きく隔てるものの 1 つが関数の振る舞いやその扱いです。関数を上手に使うことで、複雑な機能を簡潔な表現したり、シュッとしたコードの実現など、様々なメリットがあります。その反面、初めて触れるときにはわかりづらい部分も多いので、1 から詳しく説明しておこうと思います。

関数の基本

関数は以下のように宣言します。返り値の型などは明示しなくても大丈夫です。

function poyo(po, yo){
    return "poyo, " + po + "-" + yo + "!!";
}

これは極めて基本的でシンプルな形です。引数を取り、関数内にローカルな変数を宣言することができ、好きなだけ長いプログラムを書いてよく、そして return で値を返します。(return がない場合は undefined が返されます。)

関数の代入

JavaScript では変数に関数を格納することができます。この性質は以下で述べる無名関数と合わせて便利に使うことができます。以下のコードは変数に関数を格納するプリミティブなコードです。

function poyo(po, yo){
    return "poyo, " + po + "-" + yo + "!!";
}
var hoge = poyo;
console.log(hoge("ho", "ge"));
// poyo, ho-ge!!

このコードでは 関数を変数に格納 しています(驚いてほしいところ)!!C言語ではこのように変数に関数そのものを格納することはできません。C言語において関数を変数名によって間接的に呼び出そうとすると、以下のようになります。少々面倒くさいのがわかるかと思います。

#include <stdio.h>

int main(void) {
    int poyo(int a){
        return a;
    }
    int (*hoge)(int a) = *poyo;
    printf("poyo: %d\n", hoge(10));
    return 0;
}

無名関数

これまでの紹介だけだと「JavaScript は C よりも少し手間が減ったんだな!」としか思わないかもしれませんが、両者には言語として根本的な違いが存在します。それはJavaScript ではリテラル1 という数字や "poyo" という文字列のようなもの)として扱われる、ということです。なので、名前をつけることなくコード中に関数を記述することができます。

(function(po, yo) {return "poyo, " + po + "-" + yo + "!!"});
// 括弧でくくらないとエラーが出ます。
// 詳しく知りたい人は、「関数の宣言」と「関数式」で調べてみてください。

これは 名前を持たず 中身だけ定義された関数であり、 無名関数 と呼ばれています。 前項の性質より、無名関数も当然変数に代入することができます。無名関数を変数に代入することで、以下のように関数を定義することもできます。

var hoge = function(po, yo) {
    return "poyo, " + po + "-" + yo + "!!"
};
console.log(hoge("ho","ge"));
// poyo, ho-ge!!

引数関数

今までの性質を全て考慮すると、当然関数の引数として関数を渡すことが可能であること、またその関数は無名関数であっても良いことがわかるでしょう。以下のコードでは変数に代入された関数や無名関数を関数の引数として渡しています。

// 第一引数 arr の要素全てについて、それを引数とした func を実行する。
function forAllElements(arr, func){
    var length = arr.length;
    for (var i = 0; i < length; i++){
        func(arr[i]);
    }
}
// 1 ~ 5 までの数字を 2 倍して出力する。
forAllElements([1,2,3,4,5], function(d){
    console.log(2 * d);
});

今のところはひとまずこれだけで大丈夫です。クロージャやデフォルト引数、その他色々な話題について追って触れていきたいと思います。

次回予告

次回は(いつ更新されるかわかりませんが) DOM 操作やビルトインファンクションについて書きます。特にビルトインファンクションについては、これを使わないがために理解しがたい状態になっているコードが散見されましたので、余裕があるときに各自調べておいてもらえると助かります。