回答編集履歴

2 説明の補足

kura

kura score 363

2017/02/21 01:34  投稿

JavaScriptにおいて、関数の継承はこのようになっています。
- **ほとんど全ての関数** <- `%FunctionPrototype%` <- `%ObjectPrototype%` (<- `null`)
```javascript
function hoge(){}
console.log(hoge.__proto__ === Function.prototype); // true
console.log(hoge.__proto__.__proto__ === Object.prototype); // true
console.log(hoge.__proto__.__proto__.__proto__ === null); // true
```
この基本さえ抑えれば、疑問が解決するかと思います。
順に説明していきます。
##ほとんど全ての関数
**ほとんど全ての関数**とは、その名の通りJavaScriptにおけるほぼすべての関数を指します。例えば、
- `Number`, `window.alert` のような、もともと用意されている関数
- `var f = function(){};` のような、自分で作成した関数
など、通常使うすべての関数が当てはまります。
##%FunctionPrototype%
`%FunctionPrototype%`とは、**ほとんど全ての関数**が次に継承している特殊な関数です。
実際のJavaScriptでは`Function.prototype`や`function hoge(){}; hoge.__proto__`などで取得できます。
これが何のために存在するかというと、他の関数たちに関数特有のメソッドを与えるためです。
- `apply()`
- `bind()`
- `call()`
つまり、`%FunctionPrototype%`が存在するために、`func.call();` などが使えるわけですね。
```javascript
function hoge(){}
console.log(hoge.call === Function.prototype.call); // true … hoge.call は %FunctionPrototype%.call を参照している
console.log(hoge.hasOwnProperty("call")); // false … hoge 自体が call を持っているわけではない
```
##%ObjectPrototype%
最後に`%ObjectPrototype%`とは、JavaScriptのほとんどのオブジェクトが継承している特殊なオブジェクトです。
実際のJavaScriptでは`Object.prototype`や`var hoge = {}; hoge.__proto__`などで取得できます。
これが何のために存在するかというと、オブジェクトにオブジェクトらしいメソッドを与えるためです。
これが何のために存在するかというと、他のオブジェクトに基本的なメソッドを与えるためです。
- `hasOwnProperty()`
- `toString()`
 
```  
var o = {};  
console.log(o.toString()); // [object Object]  
function f(a, b, c){}  
console.log(f.hasOwnProperty("length")); // true  
```  
## 最初の疑問
最初の疑問に戻りますと、
> その場合、Function.prototype.protoということになり、これはFunction.prototypeと同じオブジェクトを参照していると思うのですが
これが実は違います。`Function.prototype`は確かに関数なのですが、関数でも`%FunctionPrototype%`という特殊な関数を指しています。
つまり、その特殊な関数のプロトタイプは、`%ObjectPrototype% (=Object.prototype)` になるわけです。
1 書式の改善

kura

kura score 363

2017/02/21 01:30  投稿

JavaScriptにおいて、関数の継承はこのようになっています。
- **ほとんど全ての関数** <- `%FunctionPrototype%` <- `%ObjectPrototype%` (<- `null`)
```javascript
function hoge(){}
console.log(hoge.__proto__ === Function.prototype); // true
console.log(hoge.__proto__.__proto__ === Object.prototype); // true
console.log(hoge.__proto__.__proto__.__proto__ === null); // true
```
この基本さえ抑えれば、疑問が解決するかと思います。
順に説明していきます。
-----
##ほとんど全ての関数
**ほとんど全ての関数**とは、その名の通りJavaScriptにおけるほぼすべての関数を指します。例えば、
- `Number`, `window.alert` のような、もともと用意されている関数
- `var f = function(){};` のような、自分で作成した関数
など、通常使うすべての関数が当てはまります。
-----
##%FunctionPrototype%
`%FunctionPrototype%`とは、**ほとんど全ての関数**が次に継承している特殊な関数です。
実際のJavaScriptでは`Function.prototype`や`function hoge(){}; hoge.__proto__`などで取得できます。
これが何のために存在するかというと、他の関数たちに関数特有のメソッドを与えるためです。
- `apply()`
- `bind()`
- `call()`
つまり、`%FunctionPrototype%`が存在するために、`func.call();` などが使えるわけですね。
```javascript
function hoge(){}
console.log(hoge.call === Function.prototype.call); // true … hoge.call は %FunctionPrototype%.call を参照している
console.log(hoge.hasOwnProperty("call")); // false … hoge 自体が call を持っているわけではない
```
-----
##%ObjectPrototype%
最後に`%ObjectPrototype%`とは、JavaScriptのほとんどのオブジェクトが継承している特殊なオブジェクトです。
実際のJavaScriptでは`Object.prototype`や`var hoge = {}; hoge.__proto__`などで取得できます。
これが何のために存在するかというと、オブジェクトにオブジェクトらしいメソッドを与えるためです。
- `hasOwnProperty()`
- `toString()`
-----
## 最初の疑問
最初の疑問に戻りますと、
> その場合、Function.prototype.protoということになり、これはFunction.prototypeと同じオブジェクトを参照していると思うのですが
これが実は違います。`Function.prototype`は確かに関数なのですが、関数でも`%FunctionPrototype%`という特殊な関数を指しています。
つまり、その特殊な関数のプロトタイプは、`%ObjectPrototype% (=Object.prototype)` になるわけです。

思考するエンジニアのためのQ&Aサイト「teratail」について詳しく知る