アクセッサプロパティ

プロパティの種類は２種類ある。

* データプロパティ・・・必ず値が格納される
* アクセッサプロパティ・・・値をもたない。そのかわり、getter,setterと呼ばれる関数を設定し、値の格納、取り出しを行う。


下記の場合、`_name`がデータプロパティ。`get name(), set name()`がアクセッサプロパティ。


```js:js
//データプロパティ
const obj = {
  name:'Tom',
  show:function(){
    console.log(name);
  }
}

//アクセッサプロパティ
var obj2 = {
  _name:'Tom', 
  get name(){  
    console.log('_nameを読み込みます');
    return this._name;
  },
  set name(value){
    console.log('_nameに'+value+'を書き込みます');
    this._name = value;
  }
};

//データプロパティ_nameにアクセス
console.log(obj2._name); //Tom

//getterにアクセス　（値の取り出し）
obj2.name;
//'_nameを読み込みます。'
//'Tom'

//setterにアクセス（値の格納）
obj2.name = 'John';
//'_nameに'John'を書き込みます'
//'John'

obj2.name;
//'_nameを読み込みます。'
//'John'
```


##プロパティアクセス

* プロパティへの、追加、変更、削除は以下の通り
* delete演算子を使う時、返り値は真偽値。削除成功ならばtrueが返る。

```js:js
const obj = {
  name:'Tom',
  show:function(){
    console.log(name);
  }
}

//プロパティアクセス
obj.name; //'Tom'  アクセス
obj.age = '18'; //追加
obj.name = 'John'; //変更
delete obj.name; //true 削除
```

**delete演算子は、プロトタイプ継承したプロパティを削除できない。しかし演算結果はtrueが返る**

```js:js
function MyClass(x, y) {
  this.x = x;
  this.y = y;
}

MyClass.prototype.show = function() {
  console.log(this.x, this.y);
}

const obj = new MyClass(2, 5);
delete obj.show //true
obj.show();
//2 5
//showメソッドは削除されず実行される
```


##プロパティの存在チェック
| 方法                 | 用途                                                 |
| -------------------- | ---------------------------------------------------- |
| hasOwnProperty       | プロトタイプ継承を除いた、プロパティの存在チェック。 |
| Object.keys()        | プロトタイプ継承を除いた、プロパティの存在チェック。 |
| in 演算子            | プロトタイプ継承も含む、プロパティの存在チェック。   |
| for(let keys in obj) | プロトタイプ継承も含む、プロパティの存在チェック。   |

```js:js
obj.hasOwnProperty('x');
//true xプロパティが存在

const keys = Object.keys(obj);
console.log(keys);
//["x", "y"]

'show' in obj;
//true

for(let keys in obj) {
  console.log(keys);
} 
//"x" "y" "show"
```


##プロパティの属性

| 属性名       | 意味                                 |
| ------------ | ------------------------------------ |
| writable     | プロパティ値を書き換え可能           |
| enumerable   | for in文で列挙可能                   |
| configurable | 属性を変更可能。プロパティの削除可能 |
| get          | プロパティ値のゲッター関数を指定可能 |
| set          | プロパティ値のセッター関数を指定可能 |

Object.getOwnPropertyDescriptor(obj, prop);で取得可能

配列のlengthプロパティは、配列のインスタンスオブジェクトのプロパティに属している。（in 演算子でtrue）。そのため、forin文で回せば、配列自身のプロパティとして列挙されるはずである。しかし、現れない。それはenumerable属性がfalseのため。

```js:js
const obj = {
  name:'Tom',
  show:function(){
    console.log(name);
  }
}

//プロパティの属性チェック
const prop = Object.getOwnPropertyDescriptor(obj, 'show');
console.log(prop);
//configurable:true
//enumerable:true
//value:ƒ ()
//writable:true
//__proto__:Object


//配列のlengthプロパティチェック
const arr = [0, 1, 3];

//in演算子でtrue
length in arr;
//true

//forin文で列挙されない
for(let keys in arr){
  console.log(keys);
}  //0 1 2

//プロパティの属性チェック
const arrProp = Object.getOwnPropertyDescriptor(arr, 'prop');
//configurable:false,
//enumerable:false,
//value:3,
//writable:true
```

##不変オブジェクト

変数にはミュータブルな型とイミュータブルな型がある。

* イミュータブルな型とは変更不可なもの。基本型はイミュータブル。数値や文字列など。
* ミュータブルな型とは変更可なもの。ArrayオブジェクトやDateオブジェクトなどは変更可な型。


####イミュータブルな型
これらは値が変更しているわけではなく、[num + 3]で新しく4という値を生成し、numに代入しているだけである。strも同じ。

```js:js
var num = 1;
num = num + 3; // numの値は4

var str = "Hello"
str = str + " World" // (1)"Hello World"
```

####ミュータブル型
array[0]の値が書き換え可能。


```js:js
const array = [1, 3, 4];
array[0] = 5; // [5, 3, 4]
```

##イミュータブルなオブジェクトをサポートする関数

上記のようなarrayオブジェクトを書き換え不可能にする関数がある。

| メソッド名        | プロパティ追加 | プロパティ削除 | プロパティ変更 | 確認メソッド        |
| ----------------- | -------------- | -------------- | -------------- | ------------------- |
| preventExtensions | ☓              | ○              | ○              | Object.isExtensible |
| Seal              | ☓              | ☓              | ○              | Object.isSealed     |
| Freeze            | ☓              | ☓              | ☓              | Object.isFrozen     |


```js:js
const array = [1, 3, 4];

//プロパティの追加だけを不可能にする
Object.preventExtensions(array);
array[1] = 20;
delete array[0];
array[3] = 10;
console.log(array);
//[undefined, 20, 4]
```