オブジェクト指向初心者の私がJavaScriptにも再入門 「JavaScriptの基本編」 〜JavaScriptパターン 学習1日目【逃げメモ】〜

*2016/5/31 タイトルを変更しました。*

# JavaScriptの基本

## 基本型とオブジェクト

JavaScriptの基本型（プリミティブ型）は、

- 数値
- 文字列
- ブール型
- null
- undefined

以上5つだけ。その他の型は **オブジェクト**に分類されます。

## 関数もオブジェクト

JavaやVBでは関数やメソッドはソレ以外のものでは無かったですが、JavaScriptの世界では **関数もオブジェクト**です。

本にはサラッと書いてありましたが、かなり重要な事なのでイメージできるようにしておこうと思います。

```js:変数に関数を代入
var hoge = function() {
	alert("hello");
}

hoge(); // hello
```

## 変数は内部オブジェクトのプロパティになる

変数を宣言すると自動的にグローバルオブジェクトのプロパティとなるそうです。

例えば、以下のhogeのような変数を宣言した場合、 **ブラウザ**で表示した時は `window`オブジェクトがグローバルオブジェクトなので、`window`オブジェクトに`hoge`プロパティが生成され、そいつを呼ぶことでその値として関数が呼び出される、といった動きになります。

`hoge()`と`window.hoge()`は等価であると言えます。

```js:変数はグローバルオブジェクトのプロパティになる
var hoge = function () {
    alert("hello");
}

hoge(); //hello
window.hoge(); //hello

if (hoge === window.hoge) alert("同一");
```

## そもそもオブジェクトとは

名前のついたプロパティの集まりであり、キーと値の組のリストでもあるようです。

Javaでいうコレクションのようなモノであり、キーを呼べば値、もしくは関数の結果（これも値だったりオブジェクトそのものだったりはするけれど）が返ってくるモノとも言えるようです。

下記のコードはオブジェクトとコレクションで同じような挙動になる事を確認してみました。

```js
/*========================
  オブジェクトでやってみる
*=======================*/

// オブジェクトの宣言とプロパティのセット
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で書ける方法とで書き比べてみました。


```Java:Javaで書いたクラス
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;
	}
}
```

```js:JavaScriptで書いてみる
//オブジェクトの生成とプロパティのセット
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日目【逃げメモ】〜](http://qiita.com/syakegon/items/1a5f0bbac49e7c4c2e88)

前回はこちら

[オブジェクト指向初心者の私がJavaScriptにも再入門 「決意表明編」 〜JavaScriptパターン 学習0日目【逃げメモ】〜](http://qiita.com/syakegon/items/3424a292d292a52da7a3)