tag:crieit.net,2005:https://crieit.net/tags/OOP/feed 「OOP」の記事 - Crieit Crieitでタグ「OOP」に投稿された最近の記事 2018-12-31T17:36:58+09:00 https://crieit.net/tags/OOP/feed tag:crieit.net,2005:PublicArticle/14704 2018-12-31T17:36:58+09:00 2018-12-31T17:36:58+09:00 https://crieit.net/posts/JavaScript-Prototype JavaScriptのPrototype周りの勉強 <p>以下のようなコードを考えてみます。</p> <pre><code class="js">function Person(f, l) { this.firstName = f; this.lastName = l; this.fullName = function() { return `${this.firstName} ${this.lastName}`; } } var a = new Person('a', 'x'); var b = new Person('b', 'y'); a.fullName(); // "a x" b.fullName(); // "b y" </code></pre> <p>ここの<code>function Person</code>は<code>new</code>キーワードを使うことで新しいオブジェクトが返されるため、オブジェクトコンストラクタと<a target="_blank" rel="nofollow noopener" href="https://developer.mozilla.org/ja/docs/Web/JavaScript/Guide/Working_with_Objects#Using_a_constructor_function">呼ばれます</a>。<br /> ここで、インスタンスはもう作られていますが、新しい関数を<code>a</code>と<code>b</code>、さらにこれから作られるすべての<code>Person</code>インスタンスに適用したいケースを考えます。ここでは、あいさつを表示する<code>greet</code>関数を加えます。</p> <pre><code class="js">Person.prototype.greet = function() { console.log(`Hello ${this.fullName()}!`); } a.greet(); // "Hello a x!" b.greet(); // "Hello b y!" // 新しいインスタンスにも適用されるかをテストする var c = new Person('c', 'z'); c.greet(); // "Hello c z! // greet関数の書き換えも可能。 Person.prototype.greet = function() { console.log(`Hello ${this.fullName()}! Have a nice day!`); } a.greet(); // Hello a x! Have a nice day! b.greet(); // Hello b y! Have a nice day! c.greet(); // Hello c z! Have a nice day! </code></pre> <p>こういうことが可能なのは、インスタンスとインスタンスの元になった<code>Person</code>は<code>Person.prototype</code>が指してるオブジェクトを共有しているからです。図にするとこうなります。<br /> <a href="https://crieit.now.sh/upload_images/a9a0272c234a2d5d0e01708773e05d415c29d1fad99dd.png" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/a9a0272c234a2d5d0e01708773e05d415c29d1fad99dd.png?mw=700" alt="JS Object prototype.png" /></a></p> <p>すべてのインスタンスが<code>Person.prototype</code>を<code>.__proto__</code>で参照しています。</p> <p>JSはクラス構造がないかわりにオブジェクト同士を参照していく<a target="_blank" rel="nofollow noopener" href="https://developer.mozilla.org/ja/docs/Web/JavaScript/Guide/Inheritance_and_the_prototype_chain">オブジェクトチェーン</a>が存在します。これは、指定されたプロパティがない場合、<code>.__proto__</code>でつながってるオブジェクトを再帰的にみていく仕組みのことです。これのおかげでインスタンスに<code>greet</code>関数がなくてもgreet関数を呼び出すことができました。</p> <p>以下参考になったリンクを張っておきます。<br /> <a target="_blank" rel="nofollow noopener" href="https://qiita.com/howdy39/items/35729490b024ca295d6c">図で理解するJavaScriptのプロトタイプチェーン</a><br /> <a target="_blank" rel="nofollow noopener" href="http://maeharin.hatenablog.com/entry/20130215/javascript_prototype_chain">や...やっと理解できた!JavaScriptのプロトタイプチェー</a></p> 1kohei1