|
| 関数ってなに? | |
|
関数とは ある処理や、複数の処理をまとめて、1つの処理群とした物です。
関数は呼出されると処理を実行します、処理ですので基本的には処理の結果を返す事ができます。
通常スクリプト内にむき出しで書き込んだ処理は、読み込まれると同時に実行されますが
関数は呼出されて始めて処理を行います。従って、状況の必要に応じて呼び出せば良いので
全体のプログラムの流れの調整に使う事も目的です。
つまり関数は、専門職人でプログラマは 必要に応じて職人を準備して、必要な時に呼び出して
使います。必要な職人はプログラムによって違いますので、どういう職人を用意するかは
あなた次第となります。
しかし、javascript全般に渡って使われるような、プログラム言語として必要なあらかじめ用意されている
職人がいます。これらを ビルトイン関数(組み込み関数)といいます。
beginnersでここまで読んでこられた方は既に出てきているのですがparseInt()やparseFloat()がそうです。
これらは、これらは、文字列を数値に変換すると言う特定の仕事をする為にjavascriptで用意されています。
従って、関数には ビルトイン関数(組み込み関数)とプログラマの作る 関数
の2種類があると言う事になりますね。
これら以外にも、職人技を取得した新しいオブジェクトを作る為のテンプレートとしてのコンストラクタにも使われます。
◆メソッドと違う?
さてここでメソッドとビルトイン関数の違いがわかりにくいですね? 違いを無理に理解する必要はないのですが
メソッドとは特定のオブジェクトに属してそのオブジェクトに対して特定処理を行います。
ビルトイン関数は特定のオブジェクトではなくもっとグローバルな範囲で動作可能なメソッドだと思ってください。
MS JScriptの組み込み関数は グローバルオブジェクトと言う架空の javascript全体を指すようなオブジェクトに対しての
メソッドである、という言い方をしています。
余計わかりづらいかもしれませんね。。。。(^^;)
メソッド: オブジェクト.プロパティ.メソッド() のように呼び出します。
window.open(); //windowオブジェクトの open()メソッド
ビルトイン関数: 関数() の様に 属するオブジェクトが無いのでそのまま書きます。
parseInt("4.05"); //属するオブジェクトが無い
何となく違う事がわからなくても全部用意されてる関数と思ってしまっても差し支えは無いと思います。
|
◆基本的な関数の定義の仕方
function 関数名(引数置換) {
処理;
処理;
処理;
}
function 関数名(引数置換) {
処理;
処理;
処理;
}
function 関数名(引数置換)
{
処理;
処理;
処理;
}
関数名 = function (引数置換)
{
処理;
処理;
処理;
}
|
上の書き方はどれも同じ事です。引数 については後で説明します。
関数(処理群)を定義するにはfunction ステートメントを使います。
関数名は自分で決めて () をつけます。
その後ろに { }を付けて、その中に1つ以上の ステートメントを記述します。
これで、この関数が呼び出されると { }内の処理が実行されます。
◆Functionオブジェクト生成
new演算子で functionオブジェクトのコンストラクタを呼び出して生成します。
var 関数名 = new function(引数1,引数2,処理)
|
この方法は通常最初から用意するような関数にはあまり使いません。
例えば、ある処理によって 新たな関数を生成する必要がある場合等に
これを使って、動的に関数を定義したりします。
あまり良い例ではありませんが、こんな感じで使えると言う例を書きます。
<script language="javascript">
var $navi = (navigator.userAgent.indexOf('MSIE') >= 0);
// msieだと true、それ以外は false になります
var $indexpage = $navi? "index_ie.html":"index_nn.html";
// trueなら index_ie.html falseなら index_nn.html が代入されます
var goindex = new function("location.href = $indexpage" );
// goindex関数は ブラウザによって中身が違う 関数となります
</script> |
この場合は ブラウザによって goindex()関数が違う内容になっています。
この例は良くないですし、普通に記述した関数 goindex()の中でブラウザ判別して
分ければ良いだけですが、この様に状況に応じて動的に関数が定義できるのが
コンストラクタを使った関数オブジェクト生成の利点です。
どちらの場合にせよ、定義された関数の扱いは同じです。
◆関数は むき出しで定義 (古)
ie4、nn4からは問題ないのですが、それ以前のブラウザでは次の場合エラーが出ます。
if(条件){
function docheck(){
}
} |
これは、if条件文の中で functionステートメントを使って関数を定義しています。
nn3ではこの様に内包される場所での定義はエラーが出るようです。
対処法としては
関数は呼び出されるまで実行されないので、外にむき出しで書いて if条件文の中には
それを呼び出す形で書き込みます。もう一つの方法はfunctionステートメントを使わず
Functionオブジェクト生成する形で関数を生成します。
◆外に書いて、呼び出して使う
function docheck(){
}
if(条件){
docheck();
}
◆オブジェクト生成で記述する
if(条件){
var docheck = new function("引数","ステートメント");
} |
現在はNN3のようなかなり古いブラウザまで考慮する方が返ってマイナス面が大きいかもしれません。
今のDOM時代に入ってからは、
条件文や関数の中でローカル関数を定義しても全然問題はありません。
if(条件){
function docheck(){ }
var dochk = function(){ }
} |
従って new function() でfunctionオブジェクトを生成する方法はほとんど使う必要が無いかと。
|
関数名の付け方の規則は、この名前を持つ関数オブジェクトと言う事になるので、
オブジェクト名の名づけ方として変数と同じです。
一応書いておきます。
・1文字以上の半角英数字、とアンダーバー( _ )、ドル記号($)を使用できます。
良例:$、_、_data、$name、list_item、age 等
悪例:age、name&mail //全角文字、アンバサンド(&) は使えません。
・先頭文字は 数字以外の半角英文字、アンダーバー、ドル記号のみになります。
悪例:1999y //数字を先頭にするのは駄目
・大文字小文字は別物扱い
例:name、name、name // それぞれが別の変数として解釈
・予約語は駄目
ここで言う予約語とは、基本的にjavascript自体ですでに使われている言葉です。
break、false、in、this、null、var、if、else その他まだまだありますが
javascript自体ですでに意味を持っている言葉を使う事ができません。
変数名のつけかたでは $をつけるとわかりやすいとも書きました。
関数の場合は関数用に自分で規則を作ってみてはどうでしょう?
直感的に理解しやすい名前を付ける事が、見やすいコーディングになります。
私の場合は DoChange()や、GetCookies()、setImages() の様に 動詞+目的語 の様な組み合わせにするのが
理解しやすくて好みのようです。
私の場合は、将来JavaScriptに新たに実装されそうなJavaScript的な書き方を使わないように、
実装されてる関数に近い表現は避けています。
|
◆引数(ひきすう)とは
引数とは関数に手渡される値の事を言います。
関数はこの値を利用する事ができます。
関数は何かしらの処理しますが、引数はこの処理に条件を付けたり、あるいは処理してもらう材料を手渡したりする物です。
・呼出し
関数名(引数);
・受け取り
function 関数名(引数置換文字){
}
|
◆引数の手渡し方
引数を関数に渡す場合は呼び出す時に関数名(引数) と言う方法で渡します。
引数の値は文字列の場合は ダブルまたはシングルクォーテーションを付けて渡します。数値や変数(オブジェクト)の場合はそのまま書き込みます。
引数は、必要な数だけ手渡せます。複数の場合はカンマ(,)で区切ります。
dochange("icon1.gif"); //文字列を引数に
dochange(1); //数値を引数に
dochange($point); //変数を引数に
dochnage(this.value); //オブジェクトを引数に
dochange("red","green","blue"); // 複数の引数を手渡す
dochange(100,5,60); //複数
|
◆引数の受け取り
引数を受け取る側の関数は、
function 関数名(引数置換1,引数置換2){
処理;
}
または
var 関数名 = new function("引数置換1","引数置換2","処理")
この様に、受け取る必要のある数だけ、受け取った値を処理で利用する為の置換え文字を用意します。
・呼出し
dochange("./img1.gif","メニュー",1);
・受け取り側関数
function dochange(a,b,c){
document.images[c].src = a;
window.status = b;
}
・受け取り側関数2
var dochange = new function("a","b","c","return a + b + c");
|
引数を受け取る時は この様に手渡された値を、関数側で a、b、c と言う引数(ローカル変数)に自動的に代入されます。
この a、b、c は この関数内でのみ有効な 変数となります。
グローバル変数や関数で使われている名前を使ってはいけません。
この様にして、受け取った引数(値)を 処理の中で使用します。
もう一つの例
・呼出し
<a href="javascript:dochange(0)">info</a>
<a href="javascript:dochange(1)">prof</a>
<a href="javascript:dochange(2)">menu</a>
・受け取り
function dochange(n){
if(n == 0){ 処理; }
if(n == 1){ 処理; }
if(n == 2){ 処理; }
}
|
htmlタグからの関数の呼出しは、別の場所に書きますが、これは アンカーを使って
javascriptの関数へ処理を渡しています。
このように引数によって、どのアンカーがクリックされたのかがわかるようにすると言う使い方も
よく使われる方法です。
引数の数や質が状況によって変わる場合等は、引数の長さ(数)を調べて取り出す事もできます。
function getdata( ){
//arguments 引数配列プロパティ
//arguments.length これは 引数の数
//arguments[i] i は数字、引数配列のi番目の値
}
|
getdataのプロパティargumentsが引数のリストをローカル配列として持っています。
◆特殊な引数
引数で気をつけなければいけないのが、イベントから関数を呼び出す場合。
サンプル1
document.onclick = test; //ハンドラで関数に渡す
function test(){
}
サンプル2
document.onclick = function(a, b){ } //イベントに無名関数を指定
|
これらは固定オブジェクトのイベントなので引数をあれこれ変える必要は基本的に無いはずです。
= test; と言う形でオブジェクト名を指定するのみで ()をつけない事で、イベントが起きたら参照と言う形です。
()をつけてしまうと、その場で実行 と言う意味に変ります。
ま、それは置いといて
こういう書き方をした場合は、Netscape系では引数0 (arguments[0]) にイベントオブジェクトが勝手に入ります。
IEで入りません。
元々、引数を受け取るような記述ではないので、IEで困る事も無いと思いますが。
タグなどにonclick="test()" の様につける時は普通の関数の呼び出しなので、引数0にイベントオブジェクトが入る事はありません。
余談:逆にこういった書き方でイベントをとる時はNetscape系ではonclick="test(event)" のように event と書いて渡してやる必要があります。
IEでもこのeventを理解できるので、タグにインラインでイベントハンドラを書いてeventを渡す場合は共通方法としてNetscapeに通用する方法で記述してください。
|
最初に書いたように、関数とはある処理をまとめて、処理をする物です。
処理をする場合には必ず結果があります。
関数を呼び出した時にその結果を戻り値として得る場合は return expression
という形で明確に返す必要があります。
逆に、戻り値が必要ない場合はreturnを使いません。
例:
function gohome(){
location.href = "./index.html";
}
この場合は locationオブジェクトの hrefプロパティに ジャンプ先のファイル(url)を指定する事で
ページがジャンプします、この場合はこの関数を呼び出した元が戻り値を必要としていません。
戻り値 return で返す方法は簡単です。関数の結果部分で
return (値・式) を指定すれば、その値や式の結果を戻します。例を使って説明します。
// ブラウザをチェックする関数 ieなら真、それ以外は偽を返す
function checknavi(){
if(navigator.useragent.indexof('msie') >=0 ){
return true;
}else{ return false; }
}
// 何らかの処理をする関数
function dotest(){
if(checknavi()){
ステートメントa;
}else{ ステートメントb;}
} |
この dotest()では if条件に 関数を指定しています。
この関数が真を返せばステートメントaを、偽を返せばステートメントbを実行します。
呼び出されたchecknavi()では navigatorオブジェクトから
ieかどうかを判断して、ieなら真、それ以外は偽を返す処理をしています。
この例では真か偽の決まった値しか返しません。
次の例は、引数を渡して処理してその結果を戻り値として得ます。
// 単純な計算をして、結果を戻します。
function calc(a,b,c){
return a*b/c;
}
function getdata(x,y){
document.forms[0].elements[0].value = calc(x,y,10);
document.forms[0].elements[1].value = calc(x,y,8);
} |
calc()では、引数を計算処理したものを 戻り値として返します。
getdata()ではそれをある任意のフォームに書き込んでいます。
この程度の簡単な計算などであれば、わざわざ関数を別に作る必要もありませんが
例えば、このgetdata()以外でも calc()で行われている処理を必要とする場合が
何ヶ所もあるとします。その場合はやはり、簡単な処理でも 1つにして引数を渡し
処理させた方が、必要な所全てに書き込まないで済むと言う点でも便利ですね?
私がよく使うのがこの様に、あちこちに散らばる同じ処理を1つにまとめてしまうと言う方法です。
また、呼び出される状況によって、必ず 戻り値を必要とする場合があります。
例えば onsubmit="関数など" と言うイベントハンドラで呼び出された場合ですが
これは、フォームのsubmitボタンが押されたら、この関数を処理してからフォーム送信します。
この時にフォームの内容をチェックして問題がある場合は false を返すと
フォーム送信が中止されます。falseを返さないと、処理されて問題があってもそのまま送信されてしまいます。
また、netscapeでは、イベントハンドラからwindow.statusの変更を行う時return true;を後ろに付けます。
<a href="" onmouseover="window.status = 'リンク'; return true;"></a>
<a href="" onmouseover="changestatus(); return true;"></a>
changestatus()はstatus表示 を変更する関数と仮定。
この様に returnが必要な場合もあります。
|
|
専用ページから申し込むと
So-netより高い3万円CB
|