0x0b
js_about_05
最終更新:
0x0b
-
view
関数
関数の定義(Defining Functions)
関数の定義は以下の関数のキーワードからなります。
関数の名前。
その関数への引数のリスト。丸括弧でくくり、コンマで区切る。
その関数を定義する JavaScript の文。波括弧 {} でくくる。関数内の文はそのアプリケーション内で定義された他の関数を呼び出すことができる。
簡単な例
その関数への引数のリスト。丸括弧でくくり、コンマで区切る。
その関数を定義する JavaScript の文。波括弧 {} でくくる。関数内の文はそのアプリケーション内で定義された他の関数を呼び出すことができる。
簡単な例
例えば、次のコードは square という名前の簡単な関数を定義します。
function square(number) { return number * number; }
関数 square は引数を 1 つとり、その名前は number です。この関数は、その引数の 2 乗を返すように指示する 1 つの文からなります。return 文は関数が返す値を指定します。
return number * number
プリミティブなパラメータは値渡しで関数に渡されます。つまり、その値は関数に渡されますが、その関数がそのパラメータの値を変更しても、この変更はグローバル(のパラメータの値)や関数の呼び出し元(のパラメータの値)には影響を与えません。
オブジェクト(すなわち 非プリミティブ値、例えば配列やユーザ定義オブジェクトなど)をパラメータとして渡すと、そのオブジェクトへの参照が関数に渡されます。つまり、その関数がそのオブジェクトのプロパティを変更した場合、その変更はその関数外でも有効です。次の例をご覧ください。
function myFunc(theObject) { theObject.make="Toyota"; } var mycar = {make:"Honda", model:"Accord", year:1998}; var x=mycar.make; // Honda を返す myFunc(mycar); var y=mycar.make; // Toyota を返す(プロパティがその関数で変更されている)
新(複写した)オブジェクトのパラメータに代入しても、呼び出し元には影響がないことに注意してください。
function myFunc(theObject) { theObject = {make:"Ford", model:"Focus", year:2006}; } var mycar = {make:"Honda", model:"Accord", year:1998}; var x=mycar.make; // Honda を返す myFunc(mycar); var y=mycar.make; // やはり Honda を返す
条件付きの関数定義
ある条件に基づいて関数を定義することもできます。例えば、次の関数の定義をご覧ください。
if (num == 0) { function myFunc(theObject) { theObject.make="Toyota" } }
変数 num が 0 に等しい場合のみ myFunc という関数が定義されます。num が 0 に等しくない場合はその関数は定義されず、その関数を実行しようとしても失敗します。
関数式
関数は式の中で定義することもできます。これは関数式と言います。一般的にこのような関数は無名です。名前を付けなくてもいいのです。例えば、関数 square は次のように定義できます。
関数は式の中で定義することもできます。これは関数式と言います。一般的にこのような関数は無名です。名前を付けなくてもいいのです。例えば、関数 square は次のように定義できます。
var square = function(number) {return number * number};
この方法はある関数を別の関数の引数として渡すときに便利です。次の例では map 関数を定義し、第 1 パラメータとして無名関数を指定して呼び出します。
この方法はある関数を別の関数の引数として渡すときに便利です。次の例では map 関数を定義し、第 1 パラメータとして無名関数を指定して呼び出します。
function map(f,a) { var result=new Array; for (var i = 0; i != a.length; i++) result[i] = f(a[i]); return result; }
次の呼び出し
map(function(x) {return x * x * x}, [0, 1, 2, 5, 10]);
は、[0, 1, 8, 125, 1000] を返します。
関連項目
関連項目
ここで述べた関数の定義に加え、Function オブジェクト を定義することもできます。
メソッドとは、あるオブジェクトに結びつけられた関数です。オブジェクトやメソッドについては 第 8 章:オブジェクトの使用 でさらに知ることができます。
関数の呼び出し(Calling Functions)
関数を定義してもその関数は自動的に実行されるわけではありません。関数を定義するということは単に関数に名前を付け、その関数が呼び出されたときに何をするかを指定することです。関数の呼び出しとは、実際には指定したパラメータを用いて指定した動作を実行するということです。例えば、関数 square を定義した場合、次のようにしてそれを呼び出すことができます。
square(5)
この文は 5 という引数とともに関数を呼び出します。関数はその関数の文を実行し、25 という値を返します。
関数の引数は文字列や数値に限られているということはありません。オブジェクト全体を関数に渡すこともできます。show_props 関数(オブジェクトとプロパティ で定義)はオブジェクトを引数にとる関数の例です。
関数は再帰的にすることもできます。つまりある関数がその関数自身を呼び出すこともできるということです。例えば、ここに階乗を計算する関数を示します。
function factorial(n) { if ((n == 0) || (n == 1)) return 1; else { var result = (n * factorial(n-1) ); return result; } }
1 から 5 までの階乗の計算は次のようになります。
a=factorial(1); // 1 を返す b=factorial(2); // 2 を返す c=factorial(3); // 6 を返す d=factorial(4); // 24 を返す e=factorial(5); // 120 を返す
argumentオブジェクトの仕様(Using the arguments object)
関数の引数は配列のようなオブジェクトで管理されます。関数内では、次のようにして渡された引数を指すことができます。
arguments[i]
ここで i は引数の順序を表す数を指します。これは 0 から始まります。関数に渡された第 1 引数は arguments[0] となります。引数のトータルの数は arguments.length で示されます。
arguments オブジェクトを使用すると、宣言時の仮引数の数よりも多くの引数を使って関数を呼び出すことができます。これはその関数に渡す引数の数が前もってわかっていない場合に役立ちます。arguments.length を使用することで実際にその関数に渡された引数の数を特定することができます。また、arguments オブジェクトを使用することで各引数を扱うことができます。
例えば、複数の文字列を連結する関数を考えます。この関数の仮引数は、連結するアイテムを区切るのに用いる文字列のみです。この関数は次のように定義されています。
function myConcat(separator) { var result = ""; // リストを初期化する // 引数について繰り返し for (var i = 1; i < arguments.length; i++) { result += arguments[i] + separator; } return result; }
この関数に引数をいくつも渡すことができます。そして各引数を文字列のリストに連結します。
// "red, orange, blue, " を返す myConcat(", ", "red", "orange", "blue"); // "elephant; giraffe; lion; cheetah; " を返す myConcat("; ", "elephant", "giraffe", "lion", "cheetah"); // "sage. basil. oregano. pepper. parsley. " を返す myConcat(". ", "sage", "basil", "oregano", "pepper", "parsley");
さらなる情報については、コア JavaScript リファレンスの Function オブジェクト をご覧ください。
JavaScript 1.3 以前のバージョン
arguments オブジェクトは Function オブジェクトのプロパティであり、次のように関数の名前を前に付けることができます。
arguments オブジェクトは Function オブジェクトのプロパティであり、次のように関数の名前を前に付けることができます。
functionName.arguments[i]
定義済み関数(Predefined Functions)
JavaScript にはトップレベルの定義済み関数がいくつかあります。
- eval
- isFinite
- isNaN
- parseInt と parseFloat
- Number と String
- encodeURI と decodeURI、encodeURIComponent、decodeURIComponent(すべて Javascript 1.5 以降で使用可能)
eval 関数
eval 関数は JavaScript のコードの文字列を特定のオブジェクトを参照することなく評価します。eval の構文は次のとおりです。
eval(expr)
ここで expr は評価される文字列です。
文字列が式を表している場合は eval はその式を評価します。また、1 つ以上の JavaScript の文を表している場合は eval はその式を実行します。eval のコードのスコープは呼び出し元コードのスコープと同じです。演算式を評価するために eval を呼び出さないでください。JavaScript は自動的に演算式を評価します。
isFinite 関数
isFinite 関数は引数を評価し、その引数が有限数であるかどうかを決定します。isFinite の構文は次のとおりです。
isFinite(number)
ここで number は評価する数値です。
引数が NaN、正の無限大、または負の無限大である場合、このメソッドは false を返し、そうでない場合は true を返します。
次のコードはクライアントの入力をチェックし、それが有限数であるかどうかを決定します。
if(isFinite(ClientInput)) { /* 適当な処理 */ }
isNaN 関数
isNaN 関数は引数を評価し、その引数が "NaN"(not a number; 非数)であるかどうかを決定します。isNaN の構文は次のとおりです。
isNaN(testValue)
ここで testValue は評価したい値です。
parseFloat および parseInt 関数は非数値を評価したときに "NaN" を返します。isNaN は "NaN" が渡された場合は true を、そうでない場合は false をそれぞれ返します。
次のコードは floatValue を評価し、それが数値であるかを決定し、その結果に応じてプロシージャを呼び出します。
floatValue=parseFloat(toFloat) if (isNaN(floatValue)) { notFloat() } else { isFloat() }
parseInt および parseFloat 関数
2 つの「パース」関数、parseInt および parseFloat は、引数に文字列が与えられたときに数値を返します。
parseFloat の構文は次のとおりです。
parseFloat(str)
parseFloat はその引数である str という文字列をパースし、浮動小数点数を返そうとします。符号(+ または -)、数字 (0-9)、小数点、または指数以外の文字に出くわすと、そこまでの値を返し、その文字とその後に続くすべての文字を無視します。最初の文字が数に変換できない場合は "NaN"(not a number; 非数)を返します。
parseInt の構文は次のとおりです。
parseInt(str [, radix])
parseInt はその第 1 引数である str という文字列をパースし、指定した radix(基数)の整数を返そうとします。radix はオプション的な第 2 引数です。例えば、10 という基数では 10 進数に変換し、8 では 8 進数、16 では 16 進数というように変換します。10 より大きな基数ではアルファベットで 9 より大きい数を表します。例えば 16 進数(基数 16)では A から F が使用されます。
parseInt は指定した基数での数値ではない文字に出くわすと、その文字とその後に続くすべての文字を無視し、それまでにパースした整数の値を返します。最初の文字が指定した基数の数に変換できない場合は "NaN" を返します。parseInt 関数は文字列を切り捨てて整数の値にします。
Number および String 関数
Number および String 関数はオブジェクトを数値や文字列に変換します。これらの関数の構文は以下のとおりです。
Number(objRef) String(objRef)
ここで objRef はオブジェクト参照を表します。
次の例では Date オブジェクトを理解できる文字列に変換します。
D = new Date (430054663215) // 次の文字列が返される // "Thu Aug 18 04:37:43 GMT-0700 (Pacific Daylight Time) 1983" x = String(D)
escape および unescape 関数
escape および unescape 関数は文字列をエンコードしたりデコードしたりします。escape 関数は ISO Latin 文字セットで表された引数の 16 進エンコーディングを返します。unescape は指定した 16 進エンコーディングの値に対する ASCII 文字列を返します。
これらの関数の構文は以下のとおりです。
escape(string) unescape(string)
これらの関数は主にサーバサイド JavaScript で URL 中の名前と値のペアのエンコードやデコードに使用されます。
escape および unescape 関数は 非 ASCII 文字に対しては正しく機能せず、廃止予定になっています。JavaScript 1.5 以降では encodeURI、decodeURI、encodeURIComponent および decodeURIComponent を使用してください。
クロージャの使用
JavaScript のオブジェクトには、それに結びつけられたプロパティがあります。簡単な記法でオブジェクトのプロパティにアクセスできます。
objectName.propertyName
オブジェクト名もプロパティ名も大文字と小文字を区別します。プロパティの定義は、そのプロパティに値を代入することで行います。例えば、myCar という名前のオブジェクトがあるとします(今回はオブジェクトが既に存在していると仮定)。次のようにして、そのオブジェクトに make、model、year という名前のプロパティをそれぞれ作成することができます。
myCar.make = "Ford"; myCar.model = "Mustang"; myCar.year = 1969;
配列はある単一の変数名に結びつけられた値の順序集合です。JavaScript におけるプロパティと配列は密接に関連しています。事実、それらは同一のデータ構造への異なるインタフェースなのです。そのため、例えば次のようにして myCar オブジェクトのプロパティにアクセスすることができます。
myCar["make"] = "Ford"; myCar["model"] = "Mustang"; myCar["year"] = 1969;
この手の配列は連想配列として知られています。それぞれのインデックスの要素が文字列にも結びつけられているからです。これがどう動作するかというと、次の関数は引数としてオブジェクトとそのオブジェクトの名前を渡すとオブジェクトのプロパティを表示します。
function show_props(obj, obj_name) { var result = ""; for (var i in obj) result += obj_name + "." + i + " = " + obj[i] + "\n"; return result; }
関数 show_props(myCar, "myCar") を呼び出すと以下の結果が返されます。
myCar.make = Ford myCar.model = Mustang myCar.year = 1969
オブジェクトの使用
オブジェクトとプロパティ
JavaScript のオブジェクトには、それに結びつけられたプロパティがあります。簡単な記法でオブジェクトのプロパティにアクセスできます。
objectName.propertyName
オブジェクト名もプロパティ名も大文字と小文字を区別します。プロパティの定義は、そのプロパティに値を代入することで行います。例えば、myCar という名前のオブジェクトがあるとします(今回はオブジェクトが既に存在していると仮定)。次のようにして、そのオブジェクトに make、model、year という名前のプロパティをそれぞれ作成することができます。
myCar.make = "Ford"; myCar.model = "Mustang"; myCar.year = 1969;
配列はある単一の変数名に結びつけられた値の順序集合です。JavaScript におけるプロパティと配列は密接に関連しています。事実、それらは同一のデータ構造への異なるインタフェースなのです。そのため、例えば次のようにして myCar オブジェクトのプロパティにアクセスすることができます。
myCar["make"] = "Ford"; myCar["model"] = "Mustang"; myCar["year"] = 1969;
この手の配列は連想配列として知られています。それぞれのインデックスの要素が文字列にも結びつけられているからです。これがどう動作するかというと、次の関数は引数としてオブジェクトとそのオブジェクトの名前を渡すとオブジェクトのプロパティを表示します。
function show_props(obj, obj_name) { var result = ""; for (var i in obj) result += obj_name + "." + i + " = " + obj[i] + "\n"; return result; }
関数 show_props(myCar, "myCar") を呼び出すと以下の結果が返されます。
myCar.make = Ford myCar.model = Mustang myCar.year = 1969
新しいオブジェクトの作成
JavaScript には多くの定義済みオブジェクトがあります。さらに、自分でオブジェクトを作り出すことができます。JavaScript 1.2 以降では、オブジェクト初期化子を用いてオブジェクトを作成できます。もう 1 つの方法として、まずコンストラクタ関数を作成し、それからその関数と new 演算子を用いてオブジェクトのインスタンスを作成することもできます。
オブジェクト初期化子の使用
コンストラクタ関数の使用
オブジェクトのプロパティのインデックス付け
あるオブジェクトの種類に対するプロパティの定義
メソッドの定義
this を用いたオブジェクト参照
ゲッタとセッタの定義
プロパティの削除
コンストラクタ関数の使用
オブジェクトのプロパティのインデックス付け
あるオブジェクトの種類に対するプロパティの定義
メソッドの定義
this を用いたオブジェクト参照
ゲッタとセッタの定義
プロパティの削除
オブジェクト初期化子の使用
コンストラクタ関数を使用してオブジェクトを作成する方法だけではなく、オブジェクト初期化子を使用してもオブジェクトを作成することができます。オブジェクト初期化子を使うことはリテラル表示を用いてオブジェクトを作成するということです。「オブジェクト初期化子」は C++ でも同じ意味で使用されている用語です。
オブジェクト初期化子を使用したオブジェクトの構文は次のとおりです。
var obj = { property_1: value_1, // property_# は識別子でもよい 2: value_2, // あるいは数値でもよい ..., "property_n": value_n }; // あるいは文字列でもよい
ここで、obj は新しいオブジェクトの名前を、各 property_i は識別子(名前、数値、文字列リテラルのいずれか)を、各 value_i はその値を property_i に代入する式をそれぞれ表しています。obj および代入部分はなくてもかまいません。このオブジェクトを別の場所で参照する必要がないのであれば変数に代入する必要はありません。(文が期待されているところにオブジェクトリテラルを置く場合、リテラルを丸括弧で囲み、ブロック文と間違われないようにする必要があるかもしれません。)
トップレベルのスクリプトでオブジェクト初期化子を使用してオブジェクトを作成した場合、JavaScript はオブジェクトリテラルを含む式を評価するたびにそのオブジェクトを解釈します。さらに、関数内で使用された初期化子はその関数が呼び出されるたびに作成されます。
次の文は、式 cond が true の場合かつその場合に限り、あるオブジェクトを作成し、それを変数 x に代入します。
if (cond) x = {hi:"there"};
次の例は 3 つのプロパティを持つ myHonda を作成します。engine プロパティは自らもプロパティを持つオブジェクトでもあることに注意してください。
myHonda = {color:"red",wheels:4,engine:{cylinders:4,size:2.2}};
オブジェクト初期化子を使用して配列を作成することもできます。配列リテラル を参照してください。
JavaScript 1.1 以前ではオブジェクト初期化子を使用することはできません。コンストラクタ関数を使用するか、他のオブジェクトが備えているそのような用途の関数を使用しないとオブジェクトを作成できません。コンストラクタ関数の使用 をご覧ください。
コンストラクタ関数の使用
もう 1 つの方法として、次の 2 つのステップでオブジェクトを作成することができます。
コンストラクタ関数を書くことでオブジェクトの種類を定義する。
new を用いてそのオブジェクトのインスタンスを作成する。
オブジェクトの種類を定義するために、その名前、プロパティ、メソッドを定義する関数を作成する必要があります。例えば、車についてのオブジェクトの種類を作成したいとします。そしてこの種類のオブジェクトに car という名前を付け、make、model、および year というプロパティを持たせたいとします。こうするためには次のような関数を書きます。
new を用いてそのオブジェクトのインスタンスを作成する。
オブジェクトの種類を定義するために、その名前、プロパティ、メソッドを定義する関数を作成する必要があります。例えば、車についてのオブジェクトの種類を作成したいとします。そしてこの種類のオブジェクトに car という名前を付け、make、model、および year というプロパティを持たせたいとします。こうするためには次のような関数を書きます。
function car(make, model, year) { this.make = make; this.model = model; this.year = year; }
関数に渡された値に基づいてオブジェクトのプロパティに値を代入するために this を使用しています。
すると、次のようにして mycar というオブジェクトを作成することができるようになります。
mycar = new car("Eagle", "Talon TSi", 1993);
この文は mycar を作成し、そのプロパティ用に指定した値を代入します。その結果、mycar.make の値は "Eagle" という文字列、mycar.year は 1993 という整数というようになります。
new を呼び出すことで car オブジェクトをいくらでも作ることができます。
kenscar = new car("Nissan", "300ZX", 1992); vpgscar = new car("Mazda", "Miata", 1990);
それ自身別のオブジェクトであるというようなプロパティを持つオブジェクトを作ることができます。例えば、次のように person というオブジェクトを定義するとします。
function person(name, age, sex) { this.name = name; this.age = age; this.sex = sex; }
そして、次のように 2 つの新しい person オブジェクトのインスタンスを作成します。
rand = new person("Rand McKinnon", 33, "M"); ken = new person("Ken Jones", 39, "M");
次のようにして、car の定義を書き換えて、person オブジェクトをとる owner プロパティを持たせることができます。
function car(make, model, year, owner) { this.make = make; this.model = model; this.year = year; this.owner = owner; }
新しいオブジェクトのインスタンスを作成するために、次のようにします。
car1 = new car("Eagle", "Talon TSi", 1993, rand); car2 = new car("Nissan", "300ZX", 1992, ken);
新しいオブジェクトの作成時に文字列リテラルや整数値を渡す代わりに、上記の文ではオブジェクト rand および ken を所有者を表す引数として渡しています。car2 の所有者の名前を知りたい場合は次のプロパティにアクセスすることで可能になります。
car2.owner.name
以前に定義したオブジェクトにいつでもプロパティを追加できることに注意してください。例えば次の文
car1.color = "black"
はプロパティ color を car1 に追加し、それに "black" という値を代入します。しかしながら、この方法では他のどのオブジェクトにも影響を与えません。同じ種類の全オブジェクトに新しいプロパティを追加するには、そのプロパティを car というオブジェクトの種類の定義に追加する必要があります。
オブジェクトのプロパティのインデックス付け
JavaScript 1.0 では、オブジェクトのプロパティを、そのプロパティ名や順序のインデックスで参照できます。しかしながら、JavaScript 1.1 以降では、最初にプロパティをその名前で定義すると、常にその名前で参照しなければならず、また、最初にプロパティをインデックスで定義すると、常にそのインデックスで参照しなければなりません。
先の Car というオブジェクトの種類の例のようにコンストラクタ関数を用いてオブジェクトとそのプロパティを作成したとき、また、それぞれのプロパティを明示的に定義したとき(例:myCar.color = "red")に、これは適用されます。そのため、myCar[5] = "25 mpg" のように、最初にインデックスを用いてオブジェクトのプロパティを定義した場合、myCar[5] のようにそのプロパティを後から参照できるようになります。
このルールの例外は、forms 配列のように HTML から反映されたオブジェクトです。これらの配列内のオブジェクトは、その順番を表す数(文書内のどこにあるかに基づく)か、またはその名前(定義されている場合)のどちらかで常に参照できます。例えば、文書内の 2 番目の <FORM> タグが "myForm" という NAME 属性を持っている場合、document.forms[1] や document.forms["myForm"] や document.myForm とすることでそのフォームを参照できます。
あるオブジェクトの種類に対するプロパティの定義
prototype プロパティを用いて、定義済みのオブジェクトの種類にプロパティを追加することができます。この方法では、指定した種類のすべてのオブジェクトで共有されるプロパティを定義することになります。そのオブジェクトのあるインスタンス 1 つだけということではありません。次のコードは color プロパティを car という種類の全オブジェクトに追加し、値をオブジェクト car1 の color プロパティに代入します。
car.prototype.color=null; car1.color="black";
詳しくは コア JavaScript リファレンス 内の Function オブジェクトの prototype プロパティ を参照してください。
メソッドの定義
メソッドとはあるオブジェクトに結びつけられた関数のことです。メソッドは、通常の関数の定義と同じ方法で定義します。既存のオブジェクトに関数を結びつけるには次の構文を使用します。
object.methodname = function_name
ここで、object は既存のオブジェクトを、methodname はメソッドに割り当てる名前を、function_name は関数の名前をそれぞれ表しています。
すると、次のようにしてオブジェクトのコンテキストでそのメソッドを呼び出すことができます。
object.methodname(params);
オブジェクトのコンストラクタ関数にメソッドの定義を含めることで、あるオブジェクトの種類についてのメソッドを定義することができます。例えば、以前に定義した car オブジェクトのプロパティを整形して表示する関数を定義します。
function displayCar() { var result = "A Beautiful " + this.year + " " + this.make + " " + this.model; pretty_print(result); }
pretty_print は水平方向の罫線と文字列を表示する関数です。this を使用してそのメソッドを抱えているオブジェクトを参照しています。
次の文
this.displayCar = displayCar;
をオブジェクトの定義に加えることで、この関数を car のメソッドにすることができます。そうすると、car の完全な定義は次のようになります。
function car(make, model, year, owner) { this.make = make; this.model = model; this.year = year; this.owner = owner; this.displayCar = displayCar; }
すると、次のようにして各オブジェクトについて displayCar メソッドを呼び出すことができます。
car1.displayCar() car2.displayCar()
this を用いたオブジェクト参照
JavaScript にはカレントオブジェクトを参照するメソッド内で使用できる特殊なキーワード、this があります。例えば、あるオブジェクトの value プロパティの妥当性を確認する validate という関数があるとします。関数にはそのオブジェクトと、上限および下限の値を渡します。
function validate(obj, lowval, hival) { if ((obj.value < lowval) || (obj.value > hival)) alert("Invalid Value!"); }
各フォーム要素の onchange イベントハンドラにおいて validate を呼び出します。this を使うことで form 要素を渡すことができます。次の例をご覧ください。
<input type="text" name="age" size="3" onChange="validate(this, 18, 99)">
一般に this はあるメソッド内でそのメソッドを呼び出したオブジェクトを参照します。
form プロパティと組み合わせることで、this はカレントオブジェクトの親のフォームを参照できます。次の例では、myForm というフォームに Text オブジェクトとボタンが格納されています。ユーザがボタンをクリックすると、Text オブジェクトの値にフォーム名がセットされます。ボタンの onclick イベントハンドラは this.form を利用して親のフォームである myForm を参照します。
<form name="myForm"> <p><label>Form name:<input type="text" name="text1" value="Beluga"></label> <p><input name="button1" type="button" value="Show Form Name" onclick="this.form.text1.value=this.form.name"> </p> </form>
ゲッタとセッタの定義
ゲッタはある特定のプロパティの値を取得するメソッドのことです。セッタはある特定のプロパティの値をセットするメソッドです。どの定義済みコアオブジェクトでも、また、新しいプロパティの追加をサポートしているユーザ定義オブジェクトでゲッタとセッタを定義することができます。ゲッタとセッタの定義にはオブジェクトリテラル構文を使用します。
以下の JS シェルセッションでは、ユーザ定義オブジェクト o についてゲッタとセッタがどう機能するかを説明します。JS シェル とは JavaScript コードをバッチモードで、またはインタラクティブにテストすることができる、開発者向けのアプリケーションのことです。
o オブジェクトのプロパティは以下のとおりです。
o.a - 数値
o.b - o.a に 1 を加えて返すゲッタ
o.c - o.a の値にその値の 1/2 の値をセットするセッタ
o.b - o.a に 1 を加えて返すゲッタ
o.c - o.a の値にその値の 1/2 の値をセットするセッタ
js> o = new Object; [object Object] js> o = {a:7, get b() {return this.a+1; }, set c(x) {this.a = x/2}}; [object Object] js> o.a 7 js> o.b 8 js> o.c = 50 js> o.a 25 js>
この JavaScript シェルセッションは、ゲッタとセッタは Date プロトタイプを拡張して定義済み Date クラスの全インスタンスに year プロパティを追加する様子を表しています。Date クラスの既存の getFullYear および setFullYear メソッドを使用して year プロパティのゲッタとセッタをサポートします。
これらの文は year プロパティに対するゲッタとセッタを定義します。
js> var d = Date.prototype; js> d.__defineGetter__("year", function() { return this.getFullYear(); }); js> d.__defineSetter__("year", function(y) { this.setFullYear(y); });
これらの文は Date オブジェクトでゲッタとセッタを使用しています。
js> var now = new Date; js> print(now.year); 2000 js> now.year=2001; 987617605170 js> print(now);
Wed Apr 18 11:13:25 GMT-0700 (Pacific Daylight Time) 2001
JavaScript 1.5 の開発期間中に getter = や setter = といった式を使用して新しいゲッタやセッタを既存のオブジェクトで定義するようになっていた時期がありました。この構文は現在は廃止予定であり、現行の JS 1.5 エンジンでは警告を発します。また、将来的には構文エラーになります。使用を避けるようにしてください
JavaScript 1.5 の開発期間中に getter = や setter = といった式を使用して新しいゲッタやセッタを既存のオブジェクトで定義するようになっていた時期がありました。この構文は現在は廃止予定であり、現行の JS 1.5 エンジンでは警告を発します。また、将来的には構文エラーになります。使用を避けるようにしてください
概要
原則的にゲッタとセッタは次のどちらかに属します。
オブジェクト初期化子 を用いて定義されたもの
ゲッタやセッタを追加するメソッドを用いてオブジェクトに後から追加されたもの
オブジェクト初期化子 を用いてゲッタやセッタを定義する際に必ずする必要があることは、ゲッタメソッドの先頭に get を、セッタメソッドの先頭に set をそれぞれ付けることです。セッタメソッドはパラメータ(セットする新しい値)を 1 つだけ受け取るようにしますが、もちろん、ゲッタメソッドはパラメータを受け取るようにしてはいけません。
ゲッタやセッタを追加するメソッドを用いてオブジェクトに後から追加されたもの
オブジェクト初期化子 を用いてゲッタやセッタを定義する際に必ずする必要があることは、ゲッタメソッドの先頭に get を、セッタメソッドの先頭に set をそれぞれ付けることです。セッタメソッドはパラメータ(セットする新しい値)を 1 つだけ受け取るようにしますが、もちろん、ゲッタメソッドはパラメータを受け取るようにしてはいけません。
o = { a:7, get b() { return this.a+1; }, set c(x) { this.a = x/2; } };
ゲッタもセッタも、__defineGetter__ および __defineSetter__ という 2 つの特別なメソッドを用いて、オブジェクト作成後にいつでもそのオブジェクトに追加することができます。両メソッドの第 1 パラメータにはそのゲッタやセッタの名前を文字列という形式で指定します。第 2 パラメータにはゲッタやセッタとして呼び出す関数を指定します。例として前の例の別バージョンを以下に示します。
o.__defineGetter__("b", function() { return this.a+1; }); o.__defineSetter__("c", function(x) { this.a = x/2; });
2 つの形式のうちどちらを選択するかはあなたのプログラミングスタイルおよび目の前の課題次第です。プロトタイプの定義時に既にオブジェクト初期化子を使用しているのであれば、最初の形式を選択するのがよいでしょう。この形式はよりコンパクトかつ自然です。しかしながら、ゲッタやセッタを後から追加する必要がある場合、プロトタイプや特定のオブジェクトを書いていないため、第 2 の形式しか使用できません。第 2 の形式は JavaScript の動的性質をおそらく最もよく表しています。しかし、コードが読みにくく、また理解しにくくなることがあります。
Firefox 3.0 より前のバージョンではゲッタとセッタが DOM 要素に対してサポートされていません。古いバージョンの Firefox では例外を投げることなく失敗します。そのときに例外が必要であれば、HTMLElement のプロトタイプを変更し (HTMLElement.prototype.__define[SG]etter__)、例外を投げるようにして回避してください。
Firefox 3.0 では、定義済みのプロパティでゲッタとセッタを定義すると例外が投げられます。そのプロパティは事前に削除しておく必要があります。これは古いバージョンの Firefox には当てはまりません。
プロパティの削除
delete 演算子を用いることでプロパティを除去することができます。次のコードでプロパティの除去方法を示します。
// 新しいオブジェクト myobj を作成。2 つのプロパティ、a および b を持つ。 myobj = new Object; myobj.a = 5; myobj.b = 12; // a プロパティを除去。myobj には b プロパティだけが残っている。 delete myobj.a;
delete を使用することでグローバル変数を削除することもできます。ただし、これは var キーワードを使用せずにその変数を宣言した場合のみです。
g = 17; delete g;
さらなる情報については delete をご覧ください。