質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.52%

  • JavaScript

    19821questions

    JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Javascriptの関数オブジェクト及びインスタンスにメソッドを追加したい

解決済

回答 2

投稿

  • 評価
  • クリップ 0
  • VIEW 1,256

SugiuraY

score 197

まだまだJavascriptの初心者なのですが、オブジェクトやprototypeチェーンの考え方を学んでいく中に単純ばことがわからなくなってしまいました。。
下記の書く内容について、もしよろしければご教示ください。

(1)下記の(A)のようにFooの関数オブジェクトに新たなメソッドを追加したいと思います。ここではfunction () {document.write("hello");}が帰ってきているのでFooオブジェクトにAメソッドが追加できていると理解して良いのでしょうか?

(2)とあるサイトで既存のオブジェクトにメソッドを追加するときはprototypeに追加すべき内容を拝見しました。(ttp://www.openspc2.org/reibun/javascript/koubun/039/)
prototypeに格納することで親も子も共通して利用出来るというざっくりした認識でいるのですが、実際に(A)と(B)で何が違うのでしょうか?
例えばここでFoo.Aでメソッドを呼び出せないことが不思議です。チェーンを辿って
function() {document.write("hello");}を呼び出してくれると認識しておりました。

(3)下記の(C)のようにインスタンスにメソッドを追加するコードはこのような形でよいのでしょうか?また、また、prototypeを利用すればFooでもアクセスできるのでしょうか?

(4)下記の(D)のように、インスタンスを利用しても4という結果を取得できない理由がわからないのですが、どこに問題があるのでしょうか?

(A)
function Foo() {}
Foo.A = function() {document.write("hello");}
console.log(Foo.A);
//function () {document.write("hello");}

(B)
function Foo() {}
Foo.prototype.A = function() {document.write("hello");}
console.log(Foo.prototype.A);
//function () {document.write("hello");}

(C)
function Foo() {}
Foo.A = function() {document.write("hello");}
var foo = new Foo();
foo.B=function() {document.write("good-bye");}
console.log(foo.B);
//function () {document.write("good-bye");}

(D)
  function Foo() {}
Foo.A = function(n) {return n+n}

var foo = new Foo(2);
console.log(foo.A);
//function (n) {return n+n}

基礎的なことかと思うのですが、どうしても理解しようと思っており、質問させていただきました。よろしくお願い申し上げます。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

+2

(1) そのとおりです。JavaScriptでは、関数もFunctionというオブジェクトです。

(2)関数オブジェクトのprototypeプロパティは、その関数オブジェクトのプロトタイプではありません。これは、関数をコンストラクタとして使った場合に、新しく作られたオブジェクトのプロトタイプとなるオブジェクトなのです。

あるオブジェクトのプロトタイプを得たい場合、Object.getPrototypeOf()を使うか、ES6で標準化された__proto__プロパティからアクセスします。なお、関数のプロトタイプオブジェクトはすべて同じ(Function.prototype)なので、そこに値を自分で追加することはあらゆる関数オブジェクトに影響してしまう、という動作の性質からプロトタイプ汚染と呼ばれ、基本的には禁じ手に近い技です。

(3)(2)で触れたように、Foo.prototype.Bを定義しておけば、インスタンスごとにメソッドをつけなくても、foo.Bとしてアクセスできます(foo.__proto__ == Foo.prototypeです)。

(4)newしても、関数オブジェクト自体にあるメソッドは引き継がれません。1つ1つ定義するか、prototypeに定義しましょう。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/01/27 07:50

    maisumakun様
    ご回答有難うございます。わかり易い回答でおおむね理解ができました。(4)についてだけ確認したいのですが、関数オブジェクトのメソッドは引き継がれないというこどですが、ともすれば関数オブジェクトのインスタンスを作る意味自体がないと言う事でしょうか?また、普通のオブジェクトも同様に、プロパティはコピーされ、メソッドはコピーされないのでしょうか?

    キャンセル

  • 2017/01/27 07:54

    他の言語で言えば「クラスメソッド」に当たるようなものを、関数オブジェクトに直接入れておく例があります。例えば、jQueryでは、jQuery()自体は関数ですが、jQuery.XXX()の形で呼び出せるメソッドは、Ajaxやユーティリティ関数のように、「jQueryのインスタンスとあまり関係しない」メソッド群となっています。

    キャンセル

checkベストアンサー

+1

 オブジェクト(連想配列)を利用するパターン

基本的な方法。

var Obj = {};

Obj.method1 = function(){...};
Obj.method2 = function(){...};


// 別パターン
var Obj = {
  method1: function(){...},
  method2: function(){...}
}

 プロトタイプを利用するパターン

前述の方法にはメモリ消費の面で無駄がある(複数コピーした場合にメソッドもコピーされる)ので、こちらの利用が推奨されます。

 方法1

  • 1つ1つのメソッドをプロトタイプに定義する形式。
  • 新たなメソッドの追加が容易。
var Constructor = function(){
  // インスタンス変数の定義
};

Constructor.prototype.method1 = function(){
  // メソッドの処理
};

Constructor.prototype.method2 = function(){
  // メソッドの処理
};

 方法2

  • Constructor.prototype = {...} を再度定義すると、以前定義したメソッド全て失われる点に注意。
var Constructor = function(){

}
Constructor.prototype = {
    method1 : function(){
      // メソッドの処理
    },
    method2 : function(){
      // メソッドの処理
    }
}

// method3を追加するつもりでこのように書いてしまうと、method1,2が失われてしまう。
Constructor.prototype = {
    method3 : function(){
      // メソッドの処理
    }
}

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/01/29 11:04

    ご回答いただき、ありがとうございます。とてもわかりやすかったです。

    キャンセル

同じタグがついた質問を見る

  • JavaScript

    19821questions

    JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。