Javascriptのインスタンス構造体で気をつけること

2019年11月2日

Javascript テクノロジー プログラミング

今回の記事はjavascript初心者向けの記事です。 プログラム勉強中の人などの参考にしてくださいませ。

インスタンスサンプル

javascriptのインスタンスは、他の言語で言うところのclassと似たような使い方をします。 // 001 function sample_1(){ console.log("This is Sample-1."); } var instance_1 = new sample_1(); // 002 var sample_2 = function(){ console.log("This is Sample-2."); } var instance_2 = sample_2(); 基本的にfunctionをインスタンス化すると覚えておくといいでしょう。 柔軟なコーディングができるjavascriptは、functionの作り方が上記の2通りありますが、どちらの場合でもインスタンス化できます。 そして、"var instance_1 = new sample_1();"のように書いていますが、"var instance_1 = new sample_1;"と記述しても同じように動作ができます。 ちなみにですが、上記2パターンの書き方で、大きな違いが発生するのは、"function ...()"と書くと、ソース内のどの位置に書いてもfunctionが認識されますが、"var ** = function(){}"の書き方は、変数定義がソース上部でされていないとundefinedになってしまいます。

インスタンスを構造体として保持してclass化する

プログラミングコードをキレイに記述することは、その後のメンテナンスや、不具合の早急な対応などに非常に役立ちます。 また、仕事などのプログラミングソースをメンテナンスする際に、ソースを記述した人以外の人が管理者になる場合の学習コストの軽減など、長い目で見ると大きなロスを防ぐことができます。 そんな中、javascriptにおいては、OSSライブラリなどを見ていると、インスタンス化できちんと構造体管理ができているものは、ソースとしてもキレイだし、見やすいし、管理しやすそうだし、何よりわかりやすいという事から以下のような構造で作るのが良さそうであると、ボク個人としてコーディングルールにしています。 window.sample = (function(){ var MAIN = function(){ new SUB(this); }; MAIN.prototype.message = function(){ console.log("This is sample-js"); }; MAIN.prototype.getURL = function(){ console.log(location.href); }; var SUB = function(main){ main.message(); main.getURL(); }; return MAIN; })(); new sample(); 行ったり来たりするプログラムで慣れないと読みにくいかもしれませんが、基本はMAIN関数にprototype以下に構成した関数群をその他の関数でコントロールするという内容で、MAINはインスタンス化された際にビルド処理にあたる感じでプログラム起動させるという構造になります。 始めは、prototypeとか、要所要所でインスタンス起動したりするのがめんどくさく感じるかもしれませんが、大きなプログラムになるほど、こうした構造体で迷子になるのが助かる経験を何度もしたので、いち早くこのような構造体に慣れたほうがいいと思いますね。

インスタンス以下の関数を直接起動する方法

ちなみに、ちょっとしたテクニックですが、インスタンス起動する時に、javascriptは関数も変数も配列も、なんでもobjectとしてjson構造で構成することができ、インスタンス以下にある関数を以下のように実行することもできます。 new sample().message(); ただし、このサンプルのままやると、MAINのインスタンス処理も含まれてしまうので、その際は親関数にあたるインスタンスするfunctionの中身は空にするか、送り値で無効化する判定をいれてあげるといいでしょう。

インスタンス内の処理についてのトラブル回避

インスタンス処理は、サンプルソースの書き方で以下のように書く事も可能です。 window.sample = (function(){ var MAIN = function(){ this.message = function(){ console.log("This is sample-js"); }; this.getURL = function(){ console.log(location.href); }; new SUB(this); }; var SUB = function(main){ main.message(); main.getURL(); }; return MAIN; })(); new sample(); prototypeは親関数の中にthisとして書き込み事で同じ構造体にすることができます。 どちらで書いても同じなのですが、過去に一度だけトラブルを経験したことがあり、以下のようなケースでした。 window.sample = (function(){ var MAIN = function(){ console.log(this.script); }; MAIN.prototype.script = (function(scripts){ return scripts[scripts.length-1].src; })(document.getElementsByTagName("script")); return MAIN; })(); new sample(); window.sample = (function(){ var MAIN = function(){ this.script = (function(scripts){ return scripts[scripts.length-1].src; })(document.getElementsByTagName("script")); console.log(this.script); }; return MAIN; })(); new sample(); このソースは、webページに貼り付けられたこのソースが記述されているscriptタグを取得する関数なのですが、prototypeで関数を記述しているケースと、thisで記述しているケースなので、同じ結果が返ると思っていたら、違う結果が返ってきたという不具合でした。 どういうことかと言うと、script関数事態は、無名関数で、実行された段階でのページ内のscriptタグの一番最後のタグを取得するようになっているのですが、prototypeの場合は、このjsファイルが読み込まれたタイミングで実行され、想定通りの結果が返りますが、thisで書かれているケースでは、MAINをnew宣言するまで、実行されないため、別のscriptタグでインスタンス化された場合、そのスクリプトの値が返ってきてしまいます。 このように、全く同じ結果が返らないという事もあるので、ちゃんと結果を認識して記述しなければいけないですね。 実はjavascriptが難しいというプログラマーの人が多いのはこうしたweb特有の事象が存在するからなのかもしれません。 これは、どんどん書いていってエラーをたくさん経験して行く以外に、習得方法はないかもしれません。 Let's try !!!!

このブログを検索

ごあいさつ

このWebサイトは、独自思考で我が道を行くユゲタの少し尖った思考のTechブログです。 毎日興味がどんどん切り替わるので、テーマはマルチになっています。 もしかしたらアイデアに困っている人の助けになるかもしれません。