17794


**質問背景**  
・単なる興味本位  
・インスタンスにprototypeは設定できないのかな、と思いました  
・prototypeは予約語ではない(？)ので，普通のプロパティとして使用可能？  
<https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Reserved_Words>

[code]

    var Hoge = function(p1) {
     this.p1 = p1;
    };
    
    Hoge.prototype = {
      m1: function() {
        return this.p1;
      }
    };
    
    var hoge = new Hoge('プ1');
    hoge.m1(); //"プ1"
    
[/code]

* * *

・自動設定されない

[code]

    hoge.prototype; //undefined
    
[/code]

* * *

・インスタンスにprototypeは自動的に設定されないようなので、手動設定に挑戦  
・目的はないです  
・挙動確認したいためだけの単なる興味本位

[code]

    hoge.prototype = {
      m2: function() {
        return this;
      }
    };
    
[/code]

* * *

・Function オブジェクトではないから？

[code]

    hoge.m2(); //Uncaught TypeError: hoge.m2 is not a function(…)
    
[/code]

* * *

・prototypeは予約語ではない(？)ので，普通のプロパティとして使用可能、ということでしょうか？

[code]

    hoge.prototype.m2(); //Object {}
    
[/code]


CC BY-SA 3.0
2015-10-19T00:20:16.087
17789
2015-10-19T02:16:58.000
7886
question
javascript
インスタンスにprototypeは自動設定されない？　無理やり設定した場合は、普通のプロパティとして取り扱われる？


prototypeについて誤解があるようです。  
Functionオブジェクトのprototypeはそれで生成したオブジェクト(this)の"prototype"に設定されるわけではありません。  
Javascriptは、オブジェクト自体に存在しないプロパティやファンクションは、そのコンストラクタのprototypeのプロパティやファンクションを探します。  
hoge.constructor.prototypeにあなたの作成したm1というファンクションを持つオブジェクトが設定されているでしょう。


CC BY-SA 3.0
2015-10-19T01:08:33.417
17792
2015-10-19T01:08:33.417
12836
17789
answer


ややこしいので、以下ではオブジェクトがプロパティを継承するオブジェクトを「プロトタイプ」、名前がたまたまprototypeであるプロパティを「prototypeプロパティ」と書きます。

オブジェクトの「prototypeプロパティ」は、そのオブジェクトの「プロトタイプ」ではありません。  
おっしゃる通り、「prototypeプロパティ」は普通のプロパティです。  
プロトタイプチェーンで「prototypeプロパティ」が参照される事はありません。  
質問の例ですと、Hogeは「prototypeプロパティ」の m1 がありますが、m1 という名前でプロパティを参照しても、これは辿られません。

[code]

    Hoge.prototype;
    // -> { m1: [Function] }
    Hoge.m1();
    // エラー
    
[/code]

では、Hogeのプロトタイプテェーンで参照される「プロトタイプ」は何なのかというと、`Object.getPrototypeOf(Hoge)`
で調べられます。Hogeは関数なので定義した時に処理系が`Function.prototype`を自動で設定しています。callプロパティ（メソッド）を調べると、プロトタイプテェーンでFunction.prototype.callが辿られているのが分かります。

[code]

    Object.getPrototypeOf(Hoge) === Function.prototype
    // -> true
    Hoge.call == Function.prototype.call
    // -> true
    
[/code]

では、「prototypeプロパティ」が普通のプロパティであるなら、いつ使われるかというと、new演算子がオブジェクトを作る時です。new
は新しいオブジェクトの「プロトタイプ」にコンストラクタオブジェクトの「prototypeプロパティ」を設定します。

[code]

    hoge = new Hoge(1);
    Hoge.prototype === Object.getPrototypeOf(hoge);
    // -> true
    
[/code]

このように、new が使う約束になっている事以外は「prototypeプロパティ」に特別な作用はないのです。

ただ、さらにややこしい事にブラウザによっては「__proto__プロパティ」という物があります。  
これは本当にオブジェクトの「プロトタイプ」を参照しており、場合によって設定し直す事も可能です。

[code]

    hoge.__proto__ = {
      m2: function() {
        return this;
      }
    };
    
    hoge.m2()
    // -> Object { p1: "プ1" }
    hoge.m1()
    // エラー: 
    // hogeの「プロトタイプ」をnew演算子が設定した物(Hogeの「prototypeプロパティ」)
    // と入れ替えたため。m1は辿れなくなった。
    
[/code]

「__proto__プロパティ」は標準でなく（後から書き換えが可能な事から性能上の問題もあるらしいです）、使うべきではありません。


CC BY-SA 3.0
2015-10-19T01:38:10.273
17794
2015-10-19T02:16:58.000
2015-10-19T02:16:58.000
3054
3054
17789
answer