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

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

ただいまの
回答率

91.25%

  • JavaScript

    11840questions

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

  • jQuery

    5085questions

    jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。

  • オブジェクト指向

    220questions

    オブジェクト指向プログラミング(Object-oriented programming;OOP)は「オブジェクト」を使用するプログラミングの概念です。オブジェクト指向プログラムは、カプセル化(情報隠蔽)とポリモーフィズム(多態性)で構成されています。

カプセル化した値を別メソッドで取得したい

解決済

回答 4

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 320
退会済みユーザー

退会済みユーザー

内容とタイトルが合致しているか、あまり自信がありません……

現在、コードは下記のようになっています。

$(function(){

  methodB();
  methodC();

    // numを外部から見えないように保持したい
  function methodA() {
    var _num;
    this.setNumber = function(num) { _num = num; }
    this.getNumber = function() { return _num; }
  }

   // numを設定する
  function methodB() {
    var a = new methodA(); // ----- ①
    a.setNumber(100);
  }

  // methodBの処理を行った後、変更されたnumの値を取得したい
  function methodC() {
    var a = new methodA(); // ----- ②
    console.log(a.getNumber());  // 出力:undefined
  }
});


このとき、methodCの出力はundefinedとなりますが、コメントにも記述されている通り、
ここではmethodBでセットした100の値を取得したいのです。

それを実現するためには、①、②の宣言(インスタンス化?)をメソッドの外に出せば可能ではあるのですが……
「いや、それならいっそのことnumの変数外に出しちゃったほうが早いじゃん!」てなってます(´・ω・`)

かなり漠然とした質問ではありますが、どのように書けばオブジェクト指向っぽくmethodCで値を取得できますか? ご教示のほど、よろしくお願いいたします。


追記: 迅速な回答ありがとうございます。 回答欄でもご指摘をいただきましたが、質問内容が漠然としすぎでしたので、追記します。

自身で上手く言語化できませんでしたが、言葉をお借りするなら、 「複数の関数 ( メソッド? ) で一つのオブジェクトを使いたい」という目的に近いです。

ただ、必要なメソッドを必要な分だけ、そのメソッド内でオブジェクト化したいのです。

現状のコードは、下記のようになっています。

$(function(){

  var a = new methodA1();
  var b = new methodA2();
  var c = new methodA3();

  methodB();
  methodC();
  methodD();

  // numの変数を保持したり取得したりするメソッド
  function methodA1() {
    var _num;
    this.setNumber = function(num) { _num = num; }
    this.getNumber = function() { return _num; }
  }

  // fooの変数を保持したり取得したりするメソッド
  function methodA2() {
    var _foo;
    this.setFoo = function(foo) { _foo= foo; }
    this.getFoo = function() { return _foo; }
  }

  // barの変数を保持したり取得したりするメソッド
  function methodA3() {
    var _bar;
    this.setBar = function(bar) { _bar = bar; }
    this.getBar = function() { return _bar; }
  }

  // いろんな値を設定する[ここではメソッドA1、メソッドA2だけ使いたい]
  function methodB() {
    a.setNumber(100);
    b.setFoo("Foo");
  }

  // いろんな値を設定する[ここではメソッドA2、メソッドA3だけ使いたい]
  function methodC() {
    b.setFoo("Foo");
    c.setBar("Bar");
  }

  // methodA1~A3の処理を行った後、変更されたnumの値を取得したい
  function methodD() {
    console.log(a.getNumber());  // 出力:100
    console.log(b.getFoo());     // 出力:Foo
    console.log(c.getBar());     // 出力:Bar
  }
});

しかし、このコードだと、methodBはメソッドA1、メソッドA2しか使わないにも関わらず、 メソッドA3も使おうと思えば使えてしまいます。 同様に、methodCもメソッドA1が使えてしまいます。

今回は、メソッドが3つの場合を挙げましたが、これが5個、10個……になってくると、 どこで何を使っているのかがかなり分かりにくくなってしまうので、 このコードの書き方は問題ありそうだなあ……と思えてきたため、質問いたしました。

それぞれのメソッドで、必要な分だけオブジェクト化して使用したいと考えています。 しかし、構造的に、どのように記述すればいいのかが分かりません(´・ω・`)

今度は、そこそこ質問の意図が明確になったような気がします……が、曖昧な箇所等あれば随時追記します。
ご教示のほど、よろしくお願いいたします。

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 4

checkベストアンサー

+2

もしもオブジェクトabcが関連するデータである場合、一つのオブジェクトにまとめたほうが綺麗だと思います。
例えば、

  // methodA1~3が定義済みであり、データa,b,cに関連性があるものとして
  function hogeDataManager() {
    this.a = new methodA1();
    this.b = new methodA2();
    this.c = new methodA3();
    this.initAB = function() {
      this.a.setNumber(100);
      this.b.setFoo("Foo");
    };
    this.initBC = function() {
      this.b.setFoo("Foo");
      this.c.setBar("Bar");
    };
    this.logAllValue = function() {
      console.log(this.a.getNumber());  // 出力:100
      console.log(this.b.getFoo());     // 出力:Foo
      console.log(this.c.getBar());     // 出力:Bar
    };
  }
  var m = new hogeDataManager();
  m.initAB(); // methodB
  m.initBC(); // methodC
  m.logAllValue(); // methodD


普通、オブジェクトにはいくつかのメンバ変数がいて、すべてのメソッドですべてのメンバ変数を使用するわけではありませんので、これでも問題はないかと思います。
ほかの場所でnewする必要があるのであれば、abcのセッターを用意すれば事足ります。

ほかにも、上記オブジェクトをabcのラッパーにしたり、オブジェクトを複数に分けず、統合してしまう(_num,_foo,_barをhogeDataManagerのメンバにしてしまう)やり方も取れます。
ラッパーは既存に少し手を加える場合によく取られる方法で、統合はオブジェクトの大きさや関連度によっては行われます。

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/01/02 17:02 編集

    回答ありがとうございます。
    非常にコンパクトにまとめられていて、感動しました。

    しかし、初歩的な質問で大変恐縮なのですが、このメソッド内部で
    設定している関数の呼び出し方がよく分かりません……

    実際にlogAllValueを外部から呼び出して値を出力するためには、どうすればいいですか?

    キャンセル

  • 2018/01/02 17:06

    hogeDataManagerをmethodA1~3と同じように使用します。一応追記しましたので、試してみてください。

    キャンセル

  • 2018/01/02 17:24

    出力できました!
    JavaScriptの経験が浅く、thisがまだうまく使いこなせていないので、
    要勉強ですね……追加回答、本当にありがとうございました。

    キャンセル

+1

情報をどういう生存期間として考えるかによってどのように管理するかは色々な戦略があると思います。

  1. モジュール単位の情報なのか
  2. 特定の文脈単位(関数を呼び出すと一時的にできる文脈など)なのか
  3. インスタンス単位の情報なのか
// 1.
var num;

// 2.
class Something {
  constructor() {
    this.num = ...;
  }
}

// 3.

function higherOrderFunction() {
  var num;

  function reference(...) {
    return ... num ...;
  }

  function sideEffect(...) {
    num = ...;
  }

  return [reference, sideEffect, ...];
}

コードからは2.か3.であろうと思えますが、オブジェクトの外部からの隠蔽(つまり2.)なのか巨大なオブジェクト実装の中のそれぞれの関数からの隠蔽なのか(つまり3.)今一つ曖昧な感じがしました。

単に文法とコード上の意味だけで論じてもかまわないと思うのですが、どのような情報をどう管理したいのか(ユースケース)の想定を明確にして論じると、より有意義な議論になるような気がします。つまり閲覧者がどこにポイントを置くかを考えやすい(回答しやすい)と思います。


追記:

追記された部分を拝見しましたが、BeatStarさんのコメントのようなアプローチで整理できる気がしました。

もしアクセスする情報ごとにメソッドのグループが単純に分類できるようならそれぞれを囲むスコープで定義するという方法もある気がします。しかしそんなにはっきりと分かれるようなら元々別のモジュールとして定義できる気がするのでそもそも解にならないのかも知れませんね・・・。それに分かり易さの点からいえば下記のv1, v2, ...のようなコンテキストをある論理的な塊のオブジェクトとしてまとめ、特にmyModule内部の関数群からそうまで厳密には区別しなくてよい気もします。そのあたりコンテキストのライフサイクルによっても適切さが変化するような気はします(下記は単純にA,Bそれぞれに静的なコンテキストだけが必要とされるケースしか表していません)

// グループA, Bがあったとして

function myModule() {
  var a1, a2, b1, b2;

  [ a1, a2 ] = (function () {
    var v1, v2, v3, ...;  // a1, a2の共通コンテキスト

    function a1() { ... }
    function a2() { ... }
    return [a1, a2];
  })();

  [ b1, b2 ] = (function () {
    var v1, v2, v3, ...; // b1, b2の共通コンテキスト

    function b1() { ... }
    function b2() { ... }
    return [b1, b2];
  })();

  // a1(), a2(), b1(), b2()などを用いた論理
  ...
}

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/01/02 13:29

    すみません。回答になってないですね・・・

    キャンセル

  • 2018/01/02 14:29

    そんなことはありません。
    そもそもの質問内容が悪かったので、加筆いたしました。
    意図した内容が少しでも明瞭化されてれば……と思います。

    キャンセル

+1

おそらく、やりたいことは以下のようなことでしょうか?

var Accessor = function(initValue) { this._value = initValue; };
Accessor.prototype.setValue = function(value) { this._value = value; };
Accessor.prototype.getValue = function() { return this._value; };

var Executor = function() {
    this._num = new Accessor(10);
    this._foo = new Accessor("foo");
    this._var = new Accessor("bar");
};

Executor.prototype.execA = function() {
    this._num.setValue(100);
    this._foo.setValue("FOO");
};

Executor.prototype.execB = function() {
    this._foo.setValue("FOO");
    this._bar.setValue("BAR");
};

Executor.prototype.execC = function() {
    console.log(this._num.getValue());
    console.log(this._foo.getValue());
    console.log(this._var.getValue());
};

var executor = new Executor();

executor.execA();
executor.execC();

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/01/02 19:43

    解決済みとした後でのコメントとなってしまい、大変申し訳ありません……
    Javaのイメージが先行して、すべてのコードを理解しているわけではありませんが、
    そうです!!質問した当初のイメージ的には、こんな感じで書きたかったんです…!!

    prototypeについて、もう少し詳しく学習した後、是非参考にさせていただきます。
    回答いただき、本当にありがとうございました。

    キャンセル

0

読解力が足りなくてすみません...

もしかして、複数の関数 ( メソッド? ) で一つのオブジェクトを使いたいということでしょうか?

それなら、

方法1:
呼び出し元( methodB, methodCを呼び出しているところ ) で、インスタンス化し、引数として渡す。

例:

// function methodAは プロトタイプだとして。

function methodB( obj ){
         obj.setNumber( 100 );
return obj;
}

function methodC( obj ){
         // 出力
}
方法2:
methodB,CそれぞれもmethodAのメンバとして定義する
方法3:
方法1に同じだが、管理クラスのようなものを設けてそれでアクセスする

例:

// すでにfunction methodAはあるとして
function methodManager(){
         // Javaとかでいうリスト構造を持っているとする。( var list[] )

         this.add = function( num ){ /* listに追加 */ }
         this.getObj = function( pos ){ /* posの位置の値を返す */ }
}

( もちろん、getObjメソッドを showメソッドとして、出力してもいいが。あくまで例。 )

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/01/02 17:34

    回答ありがとうございました。
    此方の見識が狭く、提示いただいた手法を上手く使いこなせていませんが、
    方法3の管理クラスを作成する方法は、自分なりに形を変えて採用するかもしれません。

    キャンセル

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

ただいまの回答率

91.25%

関連した質問

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

  • JavaScript

    11840questions

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

  • jQuery

    5085questions

    jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。

  • オブジェクト指向

    220questions

    オブジェクト指向プログラミング(Object-oriented programming;OOP)は「オブジェクト」を使用するプログラミングの概念です。オブジェクト指向プログラムは、カプセル化(情報隠蔽)とポリモーフィズム(多態性)で構成されています。