[JS] なんとなく分かった気になっているJSをはっきりしておく ~ Object オブジェクト Part 1 ~

# Object
JSはオブジェクト指向のプログラミング言語なので、Objectの知識は欠かせない！

Objectはそれ自体でオブジェクトで、全てのオブジェクトの最終prototypeとなります。
すでに実装されているオブジェクトのprototypeを確認するときは
~~`__proto__`~~ `Object.getPrototypeOf`を使います。
```js
Object.getPrototypeOf(Math); // Object { ... }

function Person(name) { this.name = name; }
Person.prototype.sayHello = funtion() {
    alert(`Hello! ${this.name}!`);
};
var yuchan = new Person('yuchan');
var yuchanProto = Object.getPrototypeOf(yuchan);

yuchanProto; //  { sayHello: function() }

Object.getPrototypeOf(yuchanProto); // Object { ... }
```
コンストラクターで生成されたインスタンスのprototypeのprototypeもObject オブジェクトです。
全てのオブジェクトはObjectから継承されているため、Objectのメソッドを使うことができるんです！

### オブジェクト.hasOwnProperty(プロパティー)
```js
var obj = {
    examplae: 'yes',
};
obj.example: // 'yes'
obj.hasOwnProperty('example'); // true
obj.toString; // ƒ toString() { [native code] } toStringはObjectから継承されているプロパティー
obj.hasOwnProperty('toString'); // false
```
プロパティーが対象のオブジェクトに継承されているプロパティーかどうかをチェックするメソッドです！
対象のオブジェクトから継承されているプロパティーであればtrue、親のプロパティーかそもそもプロパティーでなければfalseを返します。

### オブジェクト.isPrototypeOf(対象)
```js
var GrandParent = function() {};

var Parent = function() {};
Parent.prototype = new GrandParent();
Parent.prototype.constructor = Parent;


var Child = function() {};
Child.prototype = new Parent();
Child.prototype.constructor = Child;

var child = new Child();

Parent.prototype.isPrototypeOf(child); // true
GrandParent.prototype.isPrototypeOf(child); // true
```
オブジェクトが対象の親に当たるかどうかをチェックします。

### Object.getPrototypeOf(オブジェクト)、Object.setPrototypeOf(オブジェクト, prototype)
```js
Object.getPrototypeOf(child); // Parent {}
Object.getPrototypeOf(new GrandParent()); // {}
Object.setPrototypeOf(child, new Parent()) // 
```
最初にも書いた`Object.getPrototypeOf`はprototypeを取得、`Object.setPrototypeOf`はprototypeを設定することができます！

### instanceOf
```js
child instanceOf Parent; // true
child instanceOf GrandParent; // true
```
オブジェクトが特定のコンストラクターのインスタンスかをチェックできます！

### オブジェクト.propertyIsEnumerable(プロパティー)
```js
var obj = { name: 'Yuchan', age: 28 };

obj.propertyIsEnumerable('name'); // true
obj.propertyIsEnumerable('age'); // true
obj.propertyIsEnumerable('toString'); // false
```
オブジェクトにおいてプロパティーが列挙可能かどうかをチェックできます！

列挙可能かというのは、for...inの様なループ文内やObject.keysで使用可能かという意味です。継承されたプロパティーや対象オブジェクトのプロパティーではないものは基本除外されます。


### オブジェクト.toString()
```js
var obj = { a: 'hi', b: 'yuchan' };

obj.toString(); // [object Object]
Math.toString(); // [object Math]
console.log(`User: ${obj}`) // "User: [object Object]"
alert(obj); // [object Object]

obj.toString = function() {
    return this.a + ' ' + this.b;
}; // 適当に変えてみた

obj.toString(); // 'hi yuchan'
obj + ' kang'; // 'hi yuchan kang'
```
たまにオブジェクトをalertしたりconsole.logで叩いてみたりすると、なんかよく分からない`[object Object]`みたいなものが出力される経験はないですか？

実は内部で``toString``メソッドが呼び出されているからなんです！
主にオブジェクトが文字列の中に含まれたり、文字列と足されたりする時に呼び出されます。ユーザーが任意で変更することができます

### オブジェクト.valueOf()
```js
var obj = { a: 'hi', b: 'yuchan' };

obj.valueOf(); // { a: 'hi', b: 'yuchan' };
obj + 5; // '[object Object]5' <-- 内部でtoStringが呼び出されている

obj.valueOf = function() {
    return 3;
};

obj + 5; // 8 <-- 内部でvalueOfが呼び出されている
```
オブジェクトのデフォルト値を意味します！
toStringの様に内部で呼び出されるため扱いが難しいです。

~ 続きはPart 2で ~