• ベストアンサー

JavaScriptでArrayオブジェクトもどきの独自オブジェクトを作りたい!

お世話になります。 JavaScriptを用いて、ある条件の下でArrayオブジェクトのような独自オブジェクトを定義したいのですが、ゆっくり調べている時間がなく、こちらの方を頼らせていただくことにしました。 【やりたいこと】 Arrayオブジェクトのような独自オブジェクトを定義したい。 【やりたいことの条件】 条件1: Arrayオブジェクトが戻り値として返ってくる既存の関数があり、その戻り値であるArrayオブジェクト自身を新たなオブジェクトとして定義したい。 この関数は、 ・Arrayオブジェクトの要素とは全く無関係の引数をとる。 ・この関数の仕様を変更することはできない。 という特徴があります。 条件2: 独自オブジェクトを作る際の引数は、上述の既存の関数の引数と同じ。 【サンプル】 上記の説明では、少々わかりにくいかもしれませんので、使い方のサンプルを以下に示します。 既存の関数: function immovableFunc(param1, param2) { var myArray = new Array; … return myArray; } 今回作りたいオブジェクト: PseudoArray 今回作りたいオブジェクトの使われ方: var pa = new PseudoArray(param1, param2); そもそも、このようなオブジェクトが作れるのか?、作れるとするならばどのように記述するのか?見当も付かない状態です。 皆さんのお知恵を拝借させていただければと思います。 どうぞ、よろしくお願いいたします。

  • egeek
  • お礼率100% (5/5)

質問者が選んだベストアンサー

  • ベストアンサー
  • susie-t
  • ベストアンサー率86% (37/43)
回答No.3

> メソッドやプロパティは独自のものを使いますので、Arrayオブジェクトのメソッドやプロパティは継承しなくてもかまいません。 ということであれば、以下でどうでしょう? ----------------------------------------------------- <html> <head> <title></title> <script> var PseudoArray = function (param1, param2) { this.prop1 = param1; this.prop2 = param2; var ary = ["a", "b", "c"]; for(var i = 0; i < ary.length; i++){ this[i] = ary[i]; } }; PseudoArray.prototype = { prop1 : null, prop2 : null, method1 : function(a, b){ return (a + b + this.prop1); }, method2 : function(a, b){ return (a + b + this.prop2); } }; var pa = new PseudoArray(1, 2); var hoge1 = pa.method1(3, 4); var hoge2 = pa.method2(5, 6); var str = hoge1 + ", " + hoge2 + ", " + pa[2]; </script> </head> <body onload="document.getElementById('test').innerHTML = str;"> <div id="test"></div> </body> </html> ------------------------------------------------ 書き方はちょっと違いますが、仕組みはNo2で挙げた参考URLと一緒です。 自オブジェクトのメソッド・プロパティはthis経由で使えます。 参考になりますでしょうか。

egeek
質問者

お礼

susie-t様、再度のご回答ありがとうございます。 うまく動きました! ご回答いただいたコードを参考に、こちらの状況に合わせて下記のように書いてみました。 ----------------------------------- // テスト用スタブ // param1, param2 は無視されていますが、 // 実際は、配列の要素を決定するために使われます。 function immovableFunc(param1, param2) { var a = new Array; a[0] = 1; a[1] = "msg"; a[2] = false; return a; } function PAMethod1() { … } function PAMethod2() { … } … var PseudoArray = function(param1, param2) { var ary = immovableFunc(param1, param2); for ( var i=0; i<ary.length; i++ ) { this[i] = ary[i]; } this.prop1 = ary.length; … } PseudoArray.prototype = { prop1 : null, …, method1 : PAMethod1, method2 : PAMethod2, … } ----------------------------------- 先のご回答で 「どうしてもやるとすればArrayクラスのメソッド・プロパティを個別に指定してコピーすることになりますが・・・。」 と書かれたことだったのですね。 具体的にコードを書いてくださって、大変参考になりました。 本当にありがとうございました。 おかげさまをもちまして本件は解決したのですが、もうしばらく、質問を締め切らずに皆様のご助言を賜りたいと思いますので、ご了承願います。

その他の回答 (3)

回答No.4

> (C++でしたら、不自由せずに使える程度です)、 C++のTemplateはJavaScriptでは使えないと思いますが、 JAVA/C++のClass(JavaScriptではコンストラクター)定義+インスタンス生成の書き方もできます。 この方法なら、プライベート変数・関数とパブリック変数・関数の使い分けもできます。 function PseudoArray(param1, param2){ //public  this.prop1=param1||0;  this.prop2=param2||0;  this.method1=function(){   return prop1;  };  this.method2=function(){   return calc();  }; //private  var a=5;  function calc(){   return this.prop2+a;  } } var pa = new PseudoArray(1, 2); var a=pa.calc(); // calc not defined; var a=pa.method2(); //a=7 --------------- > var PseudoArray = function(param1, param2) { > var ary = immovableFunc(param1, param2); > for ( var i=0; i<ary.length; i++ ) { > this[i] = ary[i]; > } > this.prop1 = ary.length; > … > } aryの使い道がよくわかりませんが、 値をコピーせずに、ary自体をプライベート変数として保持しておき、値の一元管理をした方が良い様な気がします。 function PseudoArray(param1, param2) {  var ary = immovableFunc(param1, param2);  this.prop1 = ary.length;  …  this.getAry=function(id){   return ary[id];  };  this.getLength=function(){   return ary.length; //prop1の代わり  }; } var pa=new PseudoArray(1, 2); var hoge1=pa.getAry(1); alert(hoge1) // "msg" または、 this.ary=immovableFunc(param1,param2);として、pa.ary[1]で参照するかですかね。 *全角スペースでインデントしています。 *this.prop1=param1||0;  param1が指定されない場合の初期値を0にする方法です(指定がなければundefined)。 *JavaScript"らしい"書き方はprototypeだと思います。 *動作未検証です。

egeek
質問者

お礼

taloo様、再度のご回答ありがとうございます。 > JAVA/C++のClass(JavaScriptではコンストラクター)定義+インスタンス生成の書き方もできます。 > ~ 中略 ~ > var a=pa.method2(); //a=7 動く場合と動かない場合を具体的に書いてくださったので、すぐにイメージをつかめました! > aryの使い道がよくわかりませんが、 > 値をコピーせずに、ary自体をプライベート変数として保持しておき、値の一元管理をした方が良い様な気がします。 おっしゃられることはごもっともなのですが、今回作成したい PseudoArray の使われ方を変更することができませんので、どうしても、 var pa = new PseudoArray(param1, param2); var hoge = pa[*]; (← 申し訳ありません。この記述が抜けておりました。) という記述ができるオブジェクトに拘っています。 今回のような条件がない場合は、おっしゃられたように「プライベート変数として保持」という方向で考えていきたいと思います。 > *JavaScript"らしい"書き方はprototypeだと思います。 やはり、そうなんですよね。 prototype に馴染めないが故に、JavaScript に馴染めないような気がしています…(苦笑)。 書式だけに関して言えば C言語とほぼ同じということで、いきなりサンプルから JavaScript に入ったのですが、やはり根本的なところから学ぶ必要がありそうです。 とりあえずは、immovableFunc() で返ってくる結果を個々にコピーという手で進みたいと思います。 ご回答に細やかなご配慮を頂いきまして、たいへん感謝しております。 どうもありがとうございました。

egeek
質問者

補足

この場をお借りしまして、質問締め切りの連絡をさせていただきます。 taloo様、susie-t様、この度はいろいろとありがとうございました。 お二方から頂きましたご回答を参考に、JavaScript の習得にはげみたいと思います。 なお、その後の調査(思いつきによる試行?も含めて)により、下記のコードでも動きましたことをご報告申し上げます。 ------------------------------ function object(o) { function F() {} F.prototype = o; return new F(); } function PseudoArray(param1, param2) { var ary = immovableFunc(param1, param2); var pa = object(ary); pa.prop1 = ary.length; … pa.method1 = PAMethod1; pa.method2 = PAMethod2; … function PAMethod1(param3, param4) { return ret; } function PAMethod2(param5, param6) { return ret; } … return pa; } ------------------------------ どうやら、Array オブジェクトの継承ができてるようです(独自メソッドの定義内で、this.slice, this.shift などのメソッドが使えることを確認しました。)。 ただ一つ残念なことは、私自身の理解が伴っていないということでしょうか…(苦笑)。 これをもちまして、本質問を締め切らせていただきます。 サイトの主旨に従いましてポイントを付与させて頂きますが、お二方の善意に対して甲乙つけるものではないことを申し添えておきます。 この度は本当にありがとうございました。 どうぞ、今後ともよろしくお願いいたします。

  • susie-t
  • ベストアンサー率86% (37/43)
回答No.2

この条件だとちょっと無理がある気がします。 インスタンス生成(new Class();)するクラスは独自定義可能です。(参考URL参照) ただ、Arrayクラスを継承したクラスの生成はかなり面倒です。Arrayクラスのメソッド・プロパティは列挙可能でない(for inループで扱えない)場合が多いため、参考URLで紹介されている継承方法は利用できません。 どうしてもやるとすればArrayクラスのメソッド・プロパティを個別に指定してコピーすることになりますが・・・。 やはり、この場合は1の方の回答が一番素直だと思います。

参考URL:
http://www.tokumaru.org/JavaScript/
egeek
質問者

お礼

susie-t様、ご回答ありがとうございます。 やはり、無理があるのでしょうか…。 なんとなくですが、私は無茶な条件を申し上げているのではないか? という気はしているのですが…。 ですが、もう少し調査を継続したいと思いますので、さらに補足をさせてもらいます(補足ばかりで大変恐縮です。)。 メソッドやプロパティは独自のものを使いますので、Arrayオブジェクトのメソッドやプロパティは継承しなくてもかまいません。 ANo.1の補足欄で申し上げましたように、 function object(o) { function F() {} F.prototype = o; return new F(); } という記述に一縷の望みを託したい気分です。 この意味がわかれば、なんとかできるのではないかと思っているのですが…。 引き続き、情報をお待ちしたいと思います。 それと、参考URLありがとうございます。 並行して、JavaScriptの勉強をさせていただきます。 ご回答ありがとうございました。

回答No.1

function PseudoArray(param1, param2) { var myArray = new Array; … return myArray; } これでいいのではないでしょうか? newを使わずに var pa = PseudoArray(param1, param2); という書き方になりますが。

egeek
質問者

お礼

taloo様、ご回答ありがとうございます。 ご回答いただいたコードに似たようなものを私も試してみたのですが、 上記補足にも記述しましたように、プロパティとメソッドを どのようにもたせるかで躓いてしまいました。 また、 var pa = new PseudoArray(param1, param2); という使われ方もすでに決められている状況ですので、 条件を満たす方法で、なんとかできないものかと模索しております。 条件さえみたせれば、PseudoArrayは、オブジェクトでなくともかまわなのですが…。 継続して、情報をお待ちしたいと思います。 ご回答ありがとうございました。

egeek
質問者

補足

説明不足でしたので、少々補足させていただきます。 オブジェクトPseudoArrayは、 prop1, prop2 というプロパティと、 method1, method2 というメソッドを持ちます。 したがいまして、質問のサンプルに付け加えますと、 var pa = new PseudoArray(param1, param2); var hoge1 = pa.method1(param3, param4); var hoge2 = pa.method2(param5, param6); というような使われ方をします。 また、質問投稿の傍ら、継続してネット検索をしておりまして、 ------------------------------ function object(o) { function F() {} F.prototype = o; return new F(); } とすれば、Arrayなどを継承できる。 ------------------------------ という記述を見かけたのですが (ソース:http://blog.livedoor.jp/dankogai/archives/50662064.html)、 正直、今の私の知識では、上記の記述を理解することができませんでした。 オブジェクト指向は、ある程度理解しているのですが (C++でしたら、不自由せずに使える程度です)、 JavaScriptのprototypeというものに、どうも馴染めないでいる状態です。

関連するQ&A

  • JavaScriptでオブジェクトの配列

    function myfunc() {} で定義したようなオブジェクトを var arr = new Array(); arr.push()で配列に入れて、あとから取り出す際に arr[0]をmyfunc型として使うにはどうすればよいでしょうか? キャストのようなものも多分なさそうですし。

  • JavaScriptの連想配列について

    myArray = new Array();  myArray["A001"] = new Array();   myArray["A001"]["B001"] = "B001";   myArray["A001"]["B002"] = new Array();    myArray["A001"]["B002"]["C001"] = "C001";    myArray["A001"]["B002"]["C002"] = "C002";  myArray["A002"] = "A002"; JavaScriptの連想配列について質問させて頂きます。 例えば上記のような配列があったとして、値とキーはそのままで "C001" と "C002" の"B002"配列への格納順序だけ入れ替えたい場合、 どのように実装すればよろしいでしょうか? ちなみにキーや値はサンプルで実際にはsort出来るルールはありません。。。 ※入れ替え後のイメージ --------------------------------------------------------------------- myArray = new Array();  myArray["A001"] = new Array();   myArray["A001"]["B001"] = "B001";   myArray["A001"]["B002"] = new Array();    myArray["A001"]["B002"]["C002"] = "C002"; ←格納順序が    myArray["A001"]["B002"]["C001"] = "C001";  入れ替わった  myArray["A002"] = "A002"; ---------------------------------------------------------------------

  • イベントに独自引数を渡したい。

    ACTIONSCRIPT3.0で、外部ファイルを読み込ませる処理を行っているのですが、読み込み完了時の関数に独自の引数を渡すことは不可能なのでしょうか? var j:int = 100; var myArray:Array; for(var i=0;i<j;i++){  myArray[i] = new Loader();  myArray[i].load(new URLRequest(別の配列に入っている文字列のURL))  myArray[i].contentLoaderInfo.addEventListener(Event.INIT,myfunc); } function myfunc(e){イベント発生時の処理} のように、多数のイベント処理を書くときに配列のインデックスによって処理を分けたいのですが、上の例だとイベント発生時の関数であるmyfuncの引数は規定オブジェクトなので独自のものが渡せません。 いまは別にグローバルな配列を作成して処理をしているのですが、メモリ常駐になることや、オブジェクト指向として気に入らない状態です。 イベントが発生したオブジェクトの名前をキーにすることも考えましたが、どの道スマートではない。なにか方法はないものでしょうか? また、言語仕様的にやむをえないのでしょうか?

    • ベストアンサー
    • Flash
  • 【ActionScript】大量引数の効率のよい受け渡し法は?

    FLASH8(ActionScript2.0)使用者です。 ユーザー定義関数にて引数が大量にある場合、効率よく記述するにはどうすればいいのでしょうか。 現状配列で引数ひとつにまてめて処理しているのですが、関数内で展開する記述が非効率に思えます。 myArray["name"] = "taro"; myArray["age"] = 20; myArray["addr"] = "tokyo";  ・・・ function myFunc(myArray){  var name = myArray["name"];  var age = myArray["age"];  var addr = myArray["addr"];  ・・・ } この展開部分が数十に及ぶ場合、for文か何かで一発記述できればいいのに… と思うわけですがどうなんでしょうか。 「varなしにする」「配列のまま使う」 という方法もあると思いますが今回は除外させてください。 「無理」という回答でも結構です。 よろしくお願いいたします。

    • ベストアンサー
    • Flash
  • 引数を変数で渡す方法

    いつもお世話になります・。 function tst(a,b){  alert("a="+a+" b="+b) } として、 tst(1,'bbb'); とすれば a=1  b=bbb となります。 ところが、 Param="1,'bbbb'"; tst(Param); とすると、 a=1,bbb b=undefined となってしまいます。 また、 tst(eval(Param)); とすると、 a=bbb b=undefined と、なってしまいます。 また、 var Param=new array(1,'bbbb') tst(Param); とすると、何も表示されません。 引数 1,'bbb' を変数として関数に渡すにはどうしたらよいのでしょうか。 目的は、JSONで引数文字列を取得して関数に渡したいのです。 JSONで、関数に渡す引数をどのように定義したらよいものかと いうことでの質問です。 が、JSONの記載が長くなるので、 ここで質問した方法がわかれば何とか後は自分でできると思うのですが、 よろしくご教示お願いいたします。

  • どういうときにjQueryオブジェクトが返るのか

    jQueryの初心者なのですが、どういうときにjQueryオブジェクトが返るのかよくわかりません。 var sample = $(array) のように右辺がjQueryを使っていたら、左辺にもjQueryオブジェクトが入るのでしょうか?それとも、単純なdom要素が入るのでしょうか? 自分は、前者だと思っているのですが、サンプルコードを色々とみていると、 var sample = $(window); $(sample).each(function(){ }) などのように、$()でまた変数を囲っているものも見受けられます。 果たしてどうなのでしょうか? 以上、よろしくお願い致します。

  • Arrayオブジェクトとforms配列

    以下のスクリプトを実行すると、(2)の所で「document.forms.GetFromArray is not found」 のエラーとなります。(ブラウザはFirefox)。 意図としてはArrayオブジェクトをカスタマイズして追加したGetFromArray()メソッドでforms配列を操作したいのですが... エラーメッセージからすると、「document.formsは配列(Arrayオブジェクト)では無い」と言っているようです。 この方法でforms配列を参照する方法を教えて下さい。 あるいは、Arrayオブジェクトではない、他のオブジェクトをカスタマイズするのでしょうか?お願いします。 <html> <head> <script type="text/javascript"> <!-- Array.prototype.GetFromArray=function(func){ for(var i=0;i<this.length;i++){ func(this[i]); } } function disp1(h){ alert(h); } function disp2(h){ alert(h.name); } function run(){ var array=new Array('dog','cat','fish'); array.GetFromArray(disp1); //(1) OK document.forms.GetFromArray(disp2); //(2) エラー } //--> </script> </head> <body> <form name="test"> <input type="text" name="bunrui" value="分類">/ <input type="text" name="detail" value="詳細">/ <input type="button" value="実行" onClick="run();"> </form> </body> </html>

  • javascriptの標準仕様で用意されているオブジェクトを拡張しても

    javascriptの標準仕様で用意されているオブジェクトを拡張してもよいのかしら?  例えば、Arrayオブジェクトを拡張して降順ソートをやりたい時、   data=[1,2,3,4];   data.sort(function(a,b){return(b-a);});   alert(data);  のように使うのは、仕様にあるので許されると思います。   Array.prototype.descending=function(){    this.sort(function(a,b){return(b-a);});    return this;   }   data=[1,2,3,4];   alert(data.descending());  のようにArrayオブジェクトを拡張して使って問題ないでしょうか?  あるいは、   function myArray(arg){    this.descending=function(){     arg.sort(function(a,b){return(b-a);});     return arg;    }   }   data=[1,2,3,4];   data=new myArray(data);   alert(data.descending()); のように使うべきものなのでしょうか?

  • Javascriptで引数の参照渡しか戻り値を複数取得したい

    Javascriptで引数を参照渡しを行いたいのですが空で返ってきます。 どうすればよいのでしょうか? 参照渡しの引数がうまくいかない場合は戻り値を2つ返す方法と受け取る記述の仕方など知りたいです。 function test(indat, outdat, retval){ outdat = []; for (var i=0; i<indat.length; i++){ outdat[i] = indat[i]; } retval = 123; } var indat = new Array(); var outdat= new Array(); var retval = ""; indat[0] = 'A'; indat[1] = 'B'; indat[2] = 'C'; test(indat, outdat, retval); for (var i=0; i<outdat.length; i++){ alert(outdat[i]); } alert('retval=[' + retval + ']');

  • ユーザー定義オブジェクト

    現在、ユーザー定義オブジェクトについて勉強しています。 以下は本からの抜粋です。 //コンストラクタを定義する。 //thisで参照するオブジェクトの初期化法に注目   function Rectangle(w,h) { this.width=w; this.height=h; } //コンストラクタを呼び出して2つの長方形オブジェクトを生成する。 //widthとheightをコンストラクタに渡して、それぞれの新しい //オブジェクトを適切な形で初期化するやり方に注目 var rect1=new Rectangle(2,4); var rect2=new Rectangle(8.5,11); ★質問★ this.width=w; this.height=h; var rect1=new Rectangle(2,4); var rect2=new Rectangle(8.5,11); この2箇所で行っている「初期化」という作業の意味がよく分かりません。 また、ユーザー定義オブジェクトの概念についていまいちイメージ がつかめていません(特にthisとnewを使用している意図など) ご教授いただきたく、よろしくお願いします。

専門家に質問してみよう