ゴールデンウィーク最終日、やることがなくなってしまったのでブログを書きます。
前提

一口に「JavaScriptの特徴」と言っても、何の言語と比べるかによるかと思うのですが、自分が仕事で使ってきた言語は以下のようなものです。
JavaScriptの文法の特徴
引数が足りなくても、多過ぎてもOK

まずは関数を呼び出す時についてなのですが、
// 結果:”Hello, Kosuke Zaizen.”
引数が足りない時
console.log(`Hello, ${firstName} ${lastName}.`);
}
sayHello(“Kosuke”);
//結果:”Hello, Kosuke undefined.”
Javaなどのコンパイラ型言語でこんな呼び出し方をしたら、コンパイルの時点で
「引数足りてまへんで~」
「そんな引数のとり方する関数、存在してまへんで~」
って、IDEから怒られてしまいそうです。
(IDE:統合開発環境 – EclipseとかVisual Studioとか)
JavaScriptでは、受け取れなかった引数には一旦undefinedを入れて、関数が正常に実行されてしまうのですね。
引数が多過ぎるとき
個人的にもっと違和感があったのが、JavaScriptでは
「渡す引数が多すぎても問題なく実行できる」
ってところです。
以下のソースコードでは、2つの引数をとるべき関数sayHelloに対して、引数を4つも渡しています。
console.log(`Hello, ${firstName} ${lastName}.`);
}
sayHello(“Kosuke”, “Tanaka”, “Yoshida”, “Zaizen”);
//結果:”Hello, Kosuke Tanaka.”
引数を多く渡しても、何の問題もなく実行できています。
また、以下のように記述すれば、多く渡し過ぎた引数を、処理の中で用いることもできます。
console.log(`Hello, ${arguments[0]} ${arguments[1]} ${arguments[2]} ${arguments[3]}.`);
}
sayHello(“Kosuke”, “Tanaka”, “Yoshida”, “Zaizen”);
//結果:”Hello, Kosuke Tanaka Yoshida Zaizen.”
上記の形になってくると、
「関数を定義する時に(firstName, lastName)って、引数の個数を指定してる意味は??」
って思えてきます 笑
とても自由に書けちゃいます。
関数もオブジェクト

JavaScriptでは関数も「オブジェクトの一つ」とみなされるので、変数に代入できてしまいます。
console.log(`Hello, ${firstName} ${lastName}.`);
}
let saySomething;
saySomething = sayHello; //代入
saySomething(“Kosuke”, “Zaizen”);
//結果:”Hello, Kosuke Zaizen.”
上記では関数sayHelloを、変数saySomethingに代入していますね。
代入した後は、saySomethingを呼び出すことで、同様の処理が実行できていることが分かります。
(C#とかでもラムダ式を使えば、関数を変数に入れられますが… Javaでも8からはラムダ式が導入されてますね…)
メソッドもプロパティのうち

上記の「関数もオブジェクト」という点に関連するのですが、メソッドの扱いが特徴的だと思います。
普通の?オブジェクト指向言語では、
「オブジェクトとは、メソッドとプロパティを持っているものである」
って言われることが多いと思います。
ただ、JavaScriptの場合は、いわば「プロパティしかない」ような状態です。
そのプロパティに対して関数が代入された場合、特にそれをメソッドと呼んでいるに過ぎません。
つまりJavaScriptでは、メソッドはプロパティの一種であって、別の物ではありません。
JavaScriptでは「関数もオブジェクト」で、変数等に代入できるがために、「オブジェクトのプロパティに関数を代入する」なんてことができて、こんな仕様になっているのですね。
つまりオブジェクトが、ただの連想配列っぽい

結局、上記のような背景から、JavaScriptではオブジェクトというものが、すごくシンプルであるように感じます。
プロパティとメソッドが別々に分かれていて、プロパティをPrivateにしてカプセル化して……
なんてことを考えなくても、配列ぐらいのノリでオブジェクト作って、使えます。
なんだか、ただの連想配列みたいです。
連想配列とは、「キー」と「値」をセットで格納できる配列みたいなやつですね。
JavaだったらMap、RubyだったらHash、VBだったらDictionaryなどと呼ばれているやつです。
その連想配列が、JavaScriptだったら「オブジェクト」って呼ばれているだけな気がします。
JavaScriptではオブジェクトとは「キーと値をセットで持てるもの」に過ぎず、たまたま値として関数が代入されると、それをメソッドと呼ぶ。
ぐらいに考えております…
thisがコロコロ変わる

Javaなどでthisというと、
「このインスタンスの」
という言葉に言い換えられるものだと覚えていました。
クラスのプログラムを書く際に、そのクラスのメソッドの中でthisと記述することで、自分自身のインスタンスを呼び出せたのですね。
ただ、JavaScriptのオブジェクトが持っているメソッドは、変数にも入る「値」としてホイホイ受け渡せるので、
「関数が定義された時のthisと、その関数が実行されるときのthisが違う」
ということも普通にあります。
具体的なソースを見てみると…
let Hanako = {name: “花子”};
Taro.sayName = function(){
console.log(“I’m ” + this.name);
}
Hanako.sayName = Taro.sayName; //ここでthisが変わる
Hanako.sayName();
//結果:”I’m 花子”
上記では、sayNameという関数を、初めはTaroオブジェクトのメソッドとして定義しています。
このsayNameというメソッドの中でthisというキーワードが使われていますが、TaroのメソッドとしてsayNameが定義された時点では、このthisはもちろん、Taro自身を指しています。
しかしその後、sayNameメソッドは、Hanakoオブジェクトの同名のプロパティに対して、Taroオブジェクトから受け渡されています。
この時点で、HanakoオブジェクトのsayNameメソッド内のthisは、Hanakoオブジェクト自身を指すようになります。
その為、実行結果は「I’m 花子」となっています。
このようにJavaScriptではメソッドをオブジェクト間で受け渡せるため、「関数が定義された時点と、実行される時点でのthisが指す内容が異なる」ということが、よく起こります。
thisの値をコロコロ変えたくない場合は、bind関数と呼ばれるものを用いるなどの対策を行っておく必要があります。
この程度のプログラムではまだ処理が追えますが、プログラムが大きくなってくると、「thisって誰?」という状態に、僕はよくなります 笑
オブジェクトのプロパティを、後からホイホイ付け足せる

JavaScriptを自由と感じるもう一つのポイントに、
「オブジェクトのプロパティを、後からホイホイ付け足せる」
というものがあります。
(ただの「連想配列」だと考えれば、当たり前なのかも知れませんが…)
上記のTaroとHanakoのプログラムの例で言うと、以下のようにオブジェクトをリテラルで定義した時点では、sayNameなんてプロパティやメソッドは存在していません。
(リテラル:ソースコード中に定義をベタ書きすること。)
この時点ではプロパティとして、nameがあるだけです。
let Hanako = {name: “花子”};
そこに後から、
という記述を行うことで、オブジェクトに対して、行き当たりばったりでプロパティやメソッドを追加できちゃっています。
クラスとしてオブジェクトの設計図をあらかじめカッチリ決めておいて、それに従ったプロパティしか、オブジェクトは持つことができない…
なんていう堅苦しいことは、JavaScriptではないのですね…
個人的には、この性質はとても重宝しています。
//何か処理
}
という風に書けば、TaroがsayNameというプロパティを持っているかを判定できるので、様々な状態を表すプロパティを、好き勝手オブジェクトに持たせて、判定することができます。
ただ、それはあくまで個人でプログラムを書く場合であって、大人数で開発するときは、色んな人が色んな所から、好き勝手プロパティを追加していったら、収拾がつかなくなる気もします…
結論

この記事ではプログラムそのものの文法についてばかり書きましたが、何といってもJavaScriptの特徴は、
「ブラウザ側でWebの画面に動きを出せる」
ということでしょう。
もっと深くJavaScriptを理解して、ワクワクするようなUIを作っていきたいものです。
Node.jsを使えばバックエンドでもJavaScriptを書けますが、個人的にはノンブロッキングなところが扱いにくかったので、「う~ん…」という感じです…
まだNode.jsを使ったことがなくて、興味がある方は、是非サーバーサイドでのJavaScriptも試してみてください。
この記事が、JavaScriptを勉強中の方の、学習のヒントになれば幸いです。
最後までお付き合いくださり、ありがとうございました。
不備などあれば、コメントでご指摘もらえると嬉しいです。
コメント