2016/5/31 タイトルを変更しました。
JavaScriptの基本
基本型とオブジェクト
JavaScriptの基本型(プリミティブ型)は、
- 数値
- 文字列
- ブール型
- null
- undefined
以上5つだけ。その他の型は オブジェクトに分類されます。
関数もオブジェクト
JavaやVBでは関数やメソッドはソレ以外のものでは無かったですが、JavaScriptの世界では 関数もオブジェクトです。
本にはサラッと書いてありましたが、かなり重要な事なのでイメージできるようにしておこうと思います。
var hoge = function() {
alert("hello");
}
hoge(); // hello
変数は内部オブジェクトのプロパティになる
変数を宣言すると自動的にグローバルオブジェクトのプロパティとなるそうです。
例えば、以下のhogeのような変数を宣言した場合、 ブラウザで表示した時は window
オブジェクトがグローバルオブジェクトなので、window
オブジェクトにhoge
プロパティが生成され、そいつを呼ぶことでその値として関数が呼び出される、といった動きになります。
hoge()
とwindow.hoge()
は等価であると言えます。
var hoge = function () {
alert("hello");
}
hoge(); //hello
window.hoge(); //hello
if (hoge === window.hoge) alert("同一");
そもそもオブジェクトとは
名前のついたプロパティの集まりであり、キーと値の組のリストでもあるようです。
Javaでいうコレクションのようなモノであり、キーを呼べば値、もしくは関数の結果(これも値だったりオブジェクトそのものだったりはするけれど)が返ってくるモノとも言えるようです。
下記のコードはオブジェクトとコレクションで同じような挙動になる事を確認してみました。
/*========================
オブジェクトでやってみる
*=======================*/
// オブジェクトの宣言とプロパティのセット
var hoge = function () {
this.name = "ほげ";
this.age = 24;
this.welcome = function () {
return "よろしくおねがいします。";
}
}
// オブジェクト生成
var hage = new hoge();
// 呼び出し
alert("私の名前は" + hage.name + "です。年齢は" + hage.age + "です。" + hage.welcome());//私の名前はほげです。年齢は24です。よろしくおねがいします。
/*========================
コレクションでやってみる
*=======================*/
// オブジェクトの宣言
var nara = {};
// コレクションにキーと値を追加
nara["name"] = "ほげ";
nara["age"] = 24;
nara["welcome"] = function () {
return "よろしくな!";
}
// 呼び出し
alert("俺の名前は" + nara["name"] + "だ。御年" + nara["age"] + "だ。" + nara["welcome"]());//俺の名前はほげだ。御年24だ。よろしくな!
// nara["xxx"]() ←みたいに書けるんだね、やってみてビックリ!
オブジェクトのプロパティに関数を設定したもの(今回はwelcome)を メソッドと呼びます。
オブジェクトも2種類に分類する事ができます。
- ネイティブ
- ホスト
ネイティブは、組み込みオブジェクト(ArrayとかDateとか)や自分で宣言したオブジェクト(var a = {};みたいなもの)を指します。
ホストは、ブラウザなどでいうwindowやDOMオブジェクトなどを指します。
クラスが無い
Javaで今まで頑張ってきたのに、まさかクラスが無いだなんて…。
クラスとは、クラス型となるオブジェクトの一種でありますが、クラスの特徴としては、親のクラスにあるメソッドや変数(フィールド)を受け取って再利用ができる 継承や、 インタフェースを用いて多重継承の仕組みを擬似的に実現する方法などがあり、コードを再利用するための仕組みのようなものです。JavaやC#などではおなじみの機能ですね。
しかし、JavaScriptはクラスを定義することはできません。
クラスの継承を用いて新たなクラスを作成するのではなく、コンポジション(新たに作るオブジェクトの中に再利用したいオブジェクトを内包させて機能を拡張する)事の方が望ましいようで、この方法を使ってJavaScriptでクラスの表現を行うようです。
プロトタイプ
では、どうやってクラスを表現するかというと、JavaScriptで継承の仕組み利用するにはこの プロトタイプというオブジェクトを利用して表現するそうです。
プロトタイプはオブジェクトを生成した時に、暗黙的にオブジェクトに prototype
という名前のオブジェクトを生成します。中身は空のようですが、そのprototype
のconstructor
は自分が作成したコンストラクタが示されるようです。
[16:54:43.026] HtbCharactor.constructor
[16:54:43.028] (function (n, c) {this.name = n;this.color = c;})
[16:55:08.089] HtbCharactor.__proto__.constructor
[16:55:08.093] (function (n, c) {this.name = n;this.color = c;})
以下のコードでは継承を伴わないクラスをJavaで書いた時とJavaScriptで書ける方法とで書き比べてみました。
public class main {
//mainクラス
public static void main(String[] args) {
//インスタンス生成
HtbCharactor htb = new HtbCharactor("onchan", "Yellow");
//メソッド呼び出し
htb.checkNakanohito();
System.out.println(htb.getNakanohito());//安田さん
//別のインスタンス生成
HtbCharactor htb2 = new HtbCharactor("tako-seijin", "Red");
//メソッド呼び出し
htb2.checkNakanohito();
System.out.println(htb2.getNakanohito());//鈴井さんにやってもらお
}
}
//クラス宣言
class HtbCharactor {
//フィールド宣言
private String name;
private String color;
private String nakanoHito;
//コンストラクタ宣言
HtbCharactor(String name, String color) {
this.name = name;
this.color = color;
}
//メソッド宣言
protected void checkNakanohito() {
if (this.name == "onchan" && this.color == "Yellow") {
this.nakanoHito = "安田さん";
} else if (this.name == "nochan" && this.color == "Black") {
this.nakanoHito = "音尾さん";
} else {
this.nakanoHito = "鈴井さんにやってもらお";
}
}
protected String getNakanohito() {
return this.nakanoHito;
}
}
//オブジェクトの生成とプロパティのセット
HtbCharactors = function (n,c) {
this.name = n;
this.color = c;
};
//新たにプロパティのセット
HtbCharactors.prototype.nakanoHito = null;
//新たにプロパティにメソッドをセット
HtbCharactors.prototype.checkNakanohito = function () {
if (this.name == "onchan" && this.color == "Yellow") {
this.nakanoHito = "安田さん";
} else if (this.name == "nochan" && this.color == "Black") {
this.nakanoHito = "音尾さん";
} else {
this.nakanoHito = "鈴井さんにやってもらお";
}
}
//オブジェクト生成
var HtbCharactor = new HtbCharactors("onchan","Yellow");
//呼び出し
HtbCharactor.checkNakanohito();
console.log(HtbCharactor.nakanoHito); //安田さん
//別のオブジェクト生成
var HtbCharactor2 = new HtbCharactors("tako-seijin","Red");
//呼び出し
HtbCharactor2.checkNakanohito();
console.log(HtbCharactor2.nakanoHito); //鈴井さんにやってもらお
なるほど、こうすればいいわけですね。
ただJavaScriptで書いたコードで、最後の呼び出しで HtbCharactor.nakanoHito
とプロパティに直接アクセスして値を得てしまいました。これでは秘匿性が保てません。それをどうすればいいのか。
これから本を読み解いて勉強して行きます。
リンク
次回はこちら
オブジェクト指向初心者の私がJavaScriptにも再入門 「変数の扱い編」 〜JavaScriptパターン 学習2日目【逃げメモ】〜
前回はこちら
オブジェクト指向初心者の私がJavaScriptにも再入門 「決意表明編」 〜JavaScriptパターン 学習0日目【逃げメモ】〜