オブジェクトについて(Object)
・ | Object クラスについて |
・ | オブジェクトを作成する |
・ | オブジェクトツリーを構築する |
・ | Object クラスのプロパティについて |
・ | Object クラスのメソッドについて |
・ | Object クラスのデータ管理について |
・ | オブジェクトを複製する |
・ | 参照(リファレンスデータ)について |
Object クラスについて
■Object クラスについて
Object クラスは、連想配列用のクラスです。
ユニーク(唯一)な文字列をキーにして、好きなデータを格納する事ができます。
Object クラスは、すべてのオブジェクトの原型となります。
■データ型の種類について
データの型には、プリミティブ型と、リファレンス型があります。
■プリミティブ型について
プリミティブ型は、基本的で単純なデータ型です。
null、undefined、Boolean、Number、String 型が該当します。
■リファレンス型について
リファレンス型は、複合的なデータ型です。
Object、Array、Function 型など、すべてのオブジェクトが該当します。
リファレンス型については、こちらで解説しています。
オブジェクトを作成する
■Object オブジェクトを作成する
new 演算子を使って、Object クラスをインスタンス化します。
ActionScript 3.0 では、Object コンストラクタの引数から、値情報 [[PrimitiveValue]] を指定する事はできません。
ActionScript 2.0 以前の場合は、こちらで解説しています。
■作成例
空のオブジェクトを作成する
// 空の Object オブジェクトを作成する
var obj:Object = new Object();
// 出力テスト
trace(obj);
■初期データを格納しつつ Object オブジェクトを作成する
■オブジェクトリテラルを使用する
中括弧 { } の中に、キー:データ と記述します。
キーに指定する名称は、変数の命名規則に従う必要があります。
複数のデータを格納したい場合は、カンマ , で区切ります。
この書式を、オブジェクトリテラルといいます。
空の Object オブジェクトを作成する
// 空の Object オブジェクトを作成する
var obj:Object = { };
// 出力テスト
trace(obj);
オブジェクトリテラルを使って、Object オブジェクトを作成する
// ------------------------------------------------------------
// オブジェクトリテラルを使って、Object オブジェクトを作成する
// ------------------------------------------------------------
var obj:Object = { aaaaa:null , bbbbb:true , ccccc:123 , ddddd:"あいうえお" };
// ------------------------------------------------------------
// 出力テスト(ドットアクセス演算子を使ってアクセス)
// ------------------------------------------------------------
trace(obj.aaaaa); // null
trace(obj.bbbbb); // false
trace(obj.ccccc); // 123
trace(obj.ddddd); // "あいうえお"
■キーをダブルクォーテーションで括った場合
ActionScript 3.0 では、キーは、ダブルコーテーション "" で括ることができます。
キーをダブルクォーテーションで括った場合、変数の命名規則に従う必要はありません。
全角や数値などのすべての文字を、キーとして使用することができます。
オブジェクトリテラルを使って、Object オブジェクトを作成する(キーをダブルクォーテーションで括る)
// ------------------------------------------------------------
// オブジェクトリテラルを使って、Object オブジェクトを作成する
// ------------------------------------------------------------
var obj:Object = { "添字1":null , "添字2":true , "添字3":123 , "添字4":"あいうえお" };
// ------------------------------------------------------------
// 出力テスト(配列アクセス演算子を使ってアクセス)
// ------------------------------------------------------------
trace(obj["添字1"]); // null
trace(obj["添字2"]); // false
trace(obj["添字3"]); // 123
trace(obj["添字4"]); // "あいうえお"
■オブジェクトの任意のプロパティにアクセスする
オブジェクトの任意のプロパティにアクセスするには、ドットアクセス演算子か、配列アクセス演算子を使用します。
アクセスしたプロパティに、データが存在しない場合は、undefined 値が得られます。
■ドットアクセス演算子を使用する
ドットアクセス演算子は、Object.キー と記述します。
キーの名称は、変数の命名規則に従う必要があります。
ドットアクセス演算子を使って、任意のプロパティにアクセスする
var v:*;
var key:String;
// ------------------------------------------------------------
// オブジェクトを作成する
// ------------------------------------------------------------
var obj:Object = {
aaaaa:null,
bbbbb:true,
ccccc:123,
ddddd:"あいうえお"
};
// ------------------------------------------------------------
// 任意のプロパティに読み取りアクセスする
// ------------------------------------------------------------
// aaaaa プロパティからデータを取得
v = obj.aaaaa;
// 出力テスト
trace(v); // null
// ccccc プロパティからデータを取得
v = obj.ccccc;
// 出力テスト
trace(v); // 123
// ------------------------------------------------------------
// 任意のプロパティに書き込みアクセスする
// ------------------------------------------------------------
// bbbbb プロパティにデータをセット
obj.bbbbb = false;
// eeeee プロパティにデータをセット
obj.eeeee = "かきくけこ";
// ------------------------------------------------------------
// 出力テスト { aaaaa:null , bbbbb:false , ccccc:123 , ddddd:"あいうえお" , eeeee:"かきくけこ" }
// ------------------------------------------------------------
for (key in obj){
trace("---");
trace("key:" + key);
trace("data:" + obj[key]);
}
■配列アクセス演算子を使用する
配列アクセス演算子は、Object["キー"] と記述します。
キーの名称は、変数の命名規則に従う必要はありません。
配列アクセス演算子を使用すると、プロパティ名の指定を動的に制御する事ができます。
配列アクセス演算子を使って、任意のプロパティにアクセスする
var v:*;
var key:String;
// ------------------------------------------------------------
// オブジェクトを作成する
// ------------------------------------------------------------
var obj:Object = {
"添字1":null,
"添字2":true,
"添字3":123,
"添字4":"あいうえお"
};
// ------------------------------------------------------------
// 任意のプロパティに読み取りアクセスする
// ------------------------------------------------------------
// "添字1" プロパティからデータを取得
v = obj["添字1"];
// 出力テスト
trace(v); // null
// "添字3" プロパティからデータを取得
key = "添字3";
v = obj[key];
// 出力テスト
trace(v); // 123
// ------------------------------------------------------------
// 任意のプロパティに書き込みアクセスする
// ------------------------------------------------------------
// "添字2" プロパティにデータをセット
obj["添字2"] = false;
// "添字5" プロパティにデータをセット
key = "添字5";
obj[key] = "かきくけこ";
// ------------------------------------------------------------
// 出力テスト { "添字1":null , "添字2":false , "添字3":123 , "添字4":"あいうえお" , "添字5":"かきくけこ" }
// ------------------------------------------------------------
for (key in obj){
trace("---");
trace("key:" + key);
trace("data:" + obj[key]);
}
■オブジェクトのすべてのプロパティに順番にアクセスする
■ for..in 文を使用する
for..in 文を使って、アクセスする例です。
プロパティ名を取得できるので、配列アクセス演算子を使ってデータにアクセスします。
for..in 文を使用して、すべてのプロパティのデータに順番にアクセスする
// ------------------------------------------------------------
// オブジェクトを作成する
// ------------------------------------------------------------
var obj:Object = {
aaa:null,
bbb:true,
ccc:123,
ddd:"あいうえお"
};
// ------------------------------------------------------------
// for..in 文を使用して、すべてのプロパティのデータに順番にアクセスする
// ------------------------------------------------------------
var key:String;
for (key in obj){
trace("---");
trace("key:" + key);
trace("data:" + obj[key]);
}
■オブジェクトの任意のプロパティを削除する
オブジェクトの任意のプロパティを削除するには、delete 文を使用します。
オブジェクトの任意のプロパティを削除する
// ------------------------------------------------------------
// オブジェクトを作成する
// ------------------------------------------------------------
var obj:Object = {
aaa:null,
bbb:true,
ccc:123,
ddd:"あいうえお"
};
// ------------------------------------------------------------
// オブジェクトの任意のプロパティを削除する
// ------------------------------------------------------------
// aaa プロパティを削除する
delete obj.aaa;
// ccc プロパティを削除する
delete obj["ccc"];
// ------------------------------------------------------------
// 残っているプロパティをすべて出力する { bbb:true , ddd:"あいうえお" }
// ------------------------------------------------------------
var key:String;
for (key in obj){
trace("---");
trace("key:" + key);
trace("data:" + obj[key]);
}
オブジェクトツリーを構築する
■オブジェクトツリーを構築する
■オブジェクトツリーを構築するには?
Object クラスは、連想配列用のクラスです。
Object オブジェクト1つだけでは、木構造の階層を構築する事はできません。
Object オブジェクトは、ノード(節)1つとして利用できます。
オブジェクトの各プロパティに、必要な数だけ Object オブジェクトを作成して格納します。
例えば、2段の階層を持つオブジェクトツリーを構築する例です。
オブジェクトツリーを構築するには、オブジェクトの各プロパティに Object オブジェクトを作成して格納する
// オブジェクトを作成する(ルートに相当)
var obj:Object = new Object();
// オブジェクトの各プロパティに、オブジェクトを作成して格納する(ノードに相当)
obj.aaa = new Object();
obj.bbb = new Object();
obj.ccc = new Object();
■オブジェクトツリーを初期化する
オブジェクトツリーの初期化は、オブジェクトリテラルで記述すると、視覚的に見やすくなります。
オブジェクトリテラルを使って、複雑なオブジェクトツリーを構築する
var obj:Object = {
aaa:{
count:123,
name:"テスト1",
result:false
},
bbb:{
count:456,
name:"テスト2",
result:true
},
ccc:{
count:789,
name:"テスト3",
param:{
ary:["a","b","c"],
name:"テスト4"
},
result:true
}
};
■オブジェクトツリー内の任意のプロパティにアクセスする
オブジェクトツリー内の任意のプロパティにアクセスするには、ドットアクセス演算子か、配列アクセス演算子を使用します。
2段の階層を持つオブジェクトツリーにアクセスする
// ------------------------------------------------------------
// 2段の階層を持つオブジェクトツリーを作成する
// ------------------------------------------------------------
// オブジェクトを作成する(ルートに相当)
var obj:Object = new Object();
// オブジェクトの各プロパティに、オブジェクトを作成して格納する(ノードに相当)
obj.aaa = new Object();
obj.bbb = new Object();
obj.ccc = new Object();
// ------------------------------------------------------------
// 任意のプロパティに書き込みアクセスする
// ------------------------------------------------------------
// ドットアクセス演算子を使ってデータをセットする
obj.aaa.ddd = "D";
// 配列アクセス演算子を使ってデータをセットする
obj["ccc"]["eee"] = "E";
// ------------------------------------------------------------
// 任意のプロパティに読み取りアクセスする
// ------------------------------------------------------------
var v:*;
// ドットアクセス演算子を使ってデータを取得する
v = obj.aaa.ddd;
// 出力テスト
trace(v); // "D"
//配列アクセス演算子を使ってデータを取得する
v = obj["ccc"]["eee"];
// 出力テスト
trace(v); // "E"
Object クラスのプロパティについて
■Object クラスのプロパティ
Object クラスには、以下のプロパティがあります。(一部抜粋)
プロパティ | 型 | 説明 |
constructor | Function | 自身が実体化された時に使われた、コンストラクタ関数を取得します。 |
■ constructor プロパティ
コンストラクタ関数を使って、オブジェクトを生成することができます。
コンストラクタ関数については、こちらで解説しています。
実体化に使われたコンストラクタ関数を取得するには、constructor プロパティを使用します。
配列オブジェクトのコンストラクタ関数を調べる
// Array オブジェクトを作成する
var ary:Array = new Array();
// コンストラクタ関数が一致するか調べる
trace(ary.constructor == Array); // true
MyFunc オブジェクトのコンストラクタ関数を調べる
// ------------------------------------------------------------
// MyFunc という名前の関数を宣言する
// ------------------------------------------------------------
function MyFunc ():void{
}
// ------------------------------------------------------------
// MyFunc オブジェクトを作成する
// ------------------------------------------------------------
var obj:Object = new MyFunc();
// コンストラクタ関数が一致するか調べる
trace(obj.constructor == MyFunc); // true
■オブジェクトがプロトタイプチェーンである場合
constructor プロパティは、必ずしも正しい情報が得られるとは限りません。
constructor プロパティは、自身のオブジェクトが所有している訳ではありません。
コンストラクタ関数にデフォルトでセットされている、プロトタイプが所有しています。
prototype プロパティを変更してから、コンストラクタ関数を実体化した場合、自身の constructor プロパティの情報は失われている事に注意してください。
プロトタイプチェーンであるオブジェクトの constructor プロパティを調べる
// ------------------------------------------------------------
// MyFunc_A という名前の関数を宣言する
// ------------------------------------------------------------
function MyFunc_A():void{
}
// ------------------------------------------------------------
// MyFunc_B という名前の関数を宣言する
// ------------------------------------------------------------
function MyFunc_B():void{
}
// ------------------------------------------------------------
// 関数にデフォルトでセットされている、プロトタイプオブジェクトを取得する
// ------------------------------------------------------------
var prototype_a:Object = MyFunc_A.prototype;
var prototype_b:Object = MyFunc_B.prototype;
// 出力テスト
trace(prototype_a.constructor === MyFunc_A); // true
trace(prototype_b.constructor === MyFunc_B); // true
// ------------------------------------------------------------
// MyFunc_B オブジェクトを作成する(Object → MyFunc_B)
// ------------------------------------------------------------
var obj0:Object = new MyFunc_B();
// コンストラクタ関数が一致するか調べる
trace(obj0.constructor === MyFunc_B); // true
// ------------------------------------------------------------
// MyFunc_B 関数を実体化した時に、インスタンスのプロトタイプとなるオブジェクトを指定する
// ------------------------------------------------------------
MyFunc_B.prototype = new MyFunc_A();
// ------------------------------------------------------------
// MyFunc_B オブジェクトを作成する(Object → MyFunc_A → MyFunc_B)
// ------------------------------------------------------------
var obj1:Object = new MyFunc_B();
// コンストラクタ関数が一致するか調べる
trace(obj1.constructor === MyFunc_B); // false( MyFunc_B.prototype を変更したので本来の情報が失われた)
trace(obj1.constructor === MyFunc_A); // true (プロトタイプチェーンを巡って次に得られる情報)
Object クラスのメソッドについて
■Object クラスのメソッド
Object クラスには、以下のメソッドがあります。(一部抜粋)
メソッド | 説明 |
toString() | オブジェクトから文字列情報を取得する。 |
valueOf() | オブジェクトから値情報を取得する。 |
hasOwnProperty() | 指定したプロパティ名が存在するか調べる。 |
isPrototypeOf() | 自身が、指定オブジェクトのプロトタイプチェーン内に含まれるか調べる。 |
setPropertyIsEnumerable() | 指定したプロパティ名の列挙の有無を設定する。(for..in 文などで検出されるか) |
propertyIsEnumerable() | 指定したプロパティ名の列挙の有無を調べる。 |
■ toString() メソッド
オブジェクトから、文字列情報を取得するには、toString() メソッドを使用します。
日付オブジェクトから、文字列情報を取得する
// Date オブジェクトを作成する
var date_obj:Date = new Date();
// 出力テスト
trace(date_obj.toString());
■オーバーライドについて
toString() メソッドを、オーバーライドする事ができます。
toString プロパティを追加し、コールバック関数を登録します。
コールバック関数の戻り値から、好きな文字列を返します。
オブジェクトに、データの読み取りが試みられた場合、まず valueOf() メソッドが実行されます。
valueOf() メソッドから、自身のオブジェクトを返した場合、値情報無しを意味します。
オブジェクトに値情報が存在しなかった場合、次に toString() メソッドが実行されます。
文字列型として読み取られる場合、直接 toString() メソッドが実行される事もあります。
toString メソッドをオーバーライドする
// ------------------------------------------------------------
// 空のオブジェクトを作成する
// ------------------------------------------------------------
var obj:Object = new Object();
// ------------------------------------------------------------
// valueOf メソッドをオーバーライドする
// ------------------------------------------------------------
obj.valueOf = function ():*{
trace("valueOf が呼び出された");
// 自身のオブジェクトを返した場合、値情報無しを意味する
return this;
};
// ------------------------------------------------------------
// toString メソッドをオーバーライドする
// ------------------------------------------------------------
obj.toString = function ():String{
trace("toString が呼び出された");
return "オーバーライド";
};
// ------------------------------------------------------------
// 数値を足す(オブジェクトが読み取られる)
// ------------------------------------------------------------
var str:String = 12345 + obj;
// 出力テスト
trace(str); // "12345オーバーライド"
■ valueOf() メソッド
オブジェクトから、値情報を取得するには、valueOf() メソッドを使用します。
自身のオブジェクトが得られた場合、値情報が存在しない事を意味します。
Object オブジェクトから値情報を取得する
// Object オブジェクトを作成する
var obj:Object = new Object();
// 出力テスト(自身のオブジェクトが得られたので値情報は存在しない)
trace(obj.valueOf() == obj); // true
日付オブジェクトから値情報を取得する
// Date オブジェクトを作成する
var date_obj:Date = new Date();
// 出力テスト
trace(date_obj.valueOf());
■オーバーライドについて
valueOf() メソッドを、オーバーライドする事ができます。
valueOf プロパティを追加し、コールバック関数を登録します。
コールバック関数の戻り値から、好きなデータを返します。
自身のオブジェクトを返した場合、値情報無しを意味します。
オブジェクトに、読み取りが試みられた場合、valueOf() メソッドが実行されます。
オーバーライドを終了する場合、delete 文を使って、valueOf プロパティを削除します。
valueOf メソッドをオーバーライドする
// ------------------------------------------------------------
// Number オブジェクトを作成する
// ------------------------------------------------------------
var obj:Object = new Object();
// ------------------------------------------------------------
// valueOf メソッドをオーバーライドする
// ------------------------------------------------------------
obj.valueOf = function ():*{
trace("valueOf が呼び出された");
return 987;
};
// ------------------------------------------------------------
// 数値を足す(オブジェクトが読み取られる)
// ------------------------------------------------------------
var v:Number = 0 + obj;
// 出力テスト
trace(v); // 987
// ------------------------------------------------------------
// 数値として比較する(オブジェクトが読み取られる)
// ------------------------------------------------------------
if(obj > 0){
}
// ------------------------------------------------------------
// オーバーライドを終了する
// ------------------------------------------------------------
delete obj.valueOf;
■ hasOwnProperty() メソッド
オブジェクトに、指定したプロパティ名が存在するか調べるには、hasOwnProperty() メソッドを使用します。
Object.hasOwnProperty ( "プロパティ名" ) :Boolean
第01引数 | String | プロパティ名を文字列で指定 |
戻り値 | Boolean | プロパティが存在する場合 true、存在しない場合 false が得られる。 |
指定したプロパティ名が存在するか調べる
// オブジェクトを作成する
var obj:Object = new Object();
// プロパティを追加する
obj.aaa = "a";
// 出力テスト
trace(obj.hasOwnProperty("aaa")); // true
trace(obj.hasOwnProperty("bbb")); // false
■ isPrototypeOf() メソッド
自身が、指定オブジェクトのプロトタイプチェーン内に含まれるか調べるには、isPrototypeOf() メソッドを使用します。
このメソッドは、プロトタイプオブジェクトから呼び出します。
Object.isPrototypeOf ( オブジェクト ) :Boolean
第01引数 | Object | インスタンス側のオブジェクトを指定。 |
戻り値 | Boolean | プロトタイプである場合 true、該当しない場合 false が得られる。 |
配列オブジェクトのプロトタイプを確認する
// 配列オブジェクトを作成する
var ary:Array = new Array();
// Array コンストラクタから、プロトタイプオブジェクトを取得する
var prototype_obj:Object = Array.prototype;
// 出力テスト
trace(prototype_obj.isPrototypeOf(ary)); // true
プロトタイプチェーン状態にあるインスタンスのプロトタイプを確認する
// ------------------------------------------------------------
// MyFunc_A という名前の関数を宣言する
// ------------------------------------------------------------
function MyFunc_A ():void{
}
// ------------------------------------------------------------
// MyFunc_B という名前の関数を宣言する
// ------------------------------------------------------------
function MyFunc_B ():void{
}
// ------------------------------------------------------------
// MyFunc_C という名前の関数を宣言する
// ------------------------------------------------------------
function MyFunc_C ():void{
}
// ------------------------------------------------------------
// プロトタイプチェーン関係を構築する
// ------------------------------------------------------------
// MyFunc_A オブジェクトを作成する
var obj_a:Object = new MyFunc_A();
// MyFunc_B のプロトタイプにセットする
MyFunc_B.prototype = obj_a;
// MyFunc_B オブジェクトを作成する
var obj_b:Object = new MyFunc_B();
// MyFunc_C のプロトタイプにセットする
MyFunc_C.prototype = obj_b;
// ------------------------------------------------------------
// MyFunc_C オブジェクトを作成する
// ------------------------------------------------------------
var obj_c:Object = new MyFunc_C();
// ------------------------------------------------------------
// 出力テスト
// ------------------------------------------------------------
trace(obj_a.isPrototypeOf(obj_a)); // false
trace(obj_a.isPrototypeOf(obj_b)); // true
trace(obj_a.isPrototypeOf(obj_c)); // true
trace(obj_b.isPrototypeOf(obj_a)); // false
trace(obj_b.isPrototypeOf(obj_b)); // false
trace(obj_b.isPrototypeOf(obj_c)); // true
trace(obj_c.isPrototypeOf(obj_a)); // false
trace(obj_c.isPrototypeOf(obj_b)); // false
trace(obj_c.isPrototypeOf(obj_c)); // false
■ setPropertyIsEnumerable() メソッド
指定したプロパティ名の、列挙の有無を設定するには、setPropertyIsEnumerable() メソッドを使用します。
列挙を禁止すると、for..in 文などで検出できなくなります。
Object.setPropertyIsEnumerable ( "プロパティ名" , 列挙可能か? ) :void
第01引数 | Object | 設定したいプロパティ名を指定。 |
第01引数(略可) | Boolean | 列挙を許可するなら true。列挙を禁止するなら false を指定。(デフォルトは true) |
戻り値 | void | なし。 |
プロパティの列挙の有無を設定する
// ------------------------------------------------------------
// オブジェクトを作成する
// ------------------------------------------------------------
var obj:Object = new Object();
// ------------------------------------------------------------
// プロパティを追加する
// ------------------------------------------------------------
obj.aaa = "a";
obj.bbb = "b";
obj.ccc = "c";
obj.ddd = "d";
obj.eee = "e";
// ------------------------------------------------------------
// プロパティの列挙の有無を設定する
// ------------------------------------------------------------
obj.setPropertyIsEnumerable("aaa",false );
obj.setPropertyIsEnumerable("bbb",true );
obj.setPropertyIsEnumerable("ccc",false );
obj.setPropertyIsEnumerable("ddd",false );
obj.setPropertyIsEnumerable("eee",true );
// ------------------------------------------------------------
// 出力テスト "bbb" , "eee"
// ------------------------------------------------------------
var key:String;
for (key in obj){
trace(key);
}
■ propertyIsEnumerable() メソッド
指定したプロパティ名の、列挙の有無を調べるには、propertyIsEnumerable() メソッドを使用します。
Object.propertyIsEnumerable ( "プロパティ名" ) :Boolean
第01引数 | Object | 調べたいプロパティ名を指定。 |
戻り値 | Boolean | 列挙可能であれば true、列挙禁止であれば false が得られる。 |
プロパティの列挙の有無を取得する
// ------------------------------------------------------------
// オブジェクトを作成する
// ------------------------------------------------------------
var obj:Object = new Object();
// ------------------------------------------------------------
// プロパティを追加する
// ------------------------------------------------------------
obj.aaa = "a";
obj.bbb = "b";
// ------------------------------------------------------------
// プロパティの列挙の有無を設定する
// ------------------------------------------------------------
obj.setPropertyIsEnumerable("aaa",false );
obj.setPropertyIsEnumerable("bbb",true );
// ------------------------------------------------------------
// プロパティの列挙の有無を調べる
// ------------------------------------------------------------
trace(obj.propertyIsEnumerable("aaa")); // false
trace(obj.propertyIsEnumerable("bbb")); // true
Object クラスのデータ管理について
■Object オブジェクトを辞書として使用する
Object オブジェクトは、文字列をキーとした辞書として取り扱う事ができます。
ActionScript 3.0 では、辞書機能に特化した、Dictionary クラスもあります。
■辞書として取り扱う理由
Object オブジェクトは、内部でハッシュテーブルを使った高速化が実現されています。
文字列をキーとして指定することで、該当するデータを高速で検索する事ができます。
また、すべてのデータの中から該当するデータが存在しない事を、高速で判別する事もできます。
データの総数が、100 万以上ある場合でも、瞬時に検索できます。
■辞書として管理するためには?
データごとに、ユニーク(唯一)な識別名が、存在している必要があります。
例えば、以下の様なアドレス情報は、辞書として管理することができます。
辞書として管理するためには、データごとにユニークな識別名が必要
var page_a:Object = { url:"http://example.com/a.html", title:"タイトルA", size:1310 };
var page_b:Object = { url:"http://example.com/b.html", title:"タイトルB", size:2621 };
var page_c:Object = { url:"http://example.com/c.html", title:"タイトルC", size:5242 };
var page_x:Object = { url:"http://example.com/x.html", title:"×××××", size:9999 };
var page_y:Object = { url:"http://example.com/y.html", title:"×××××", size:9999 };
var page_z:Object = { url:"http://example.com/z.html", title:"×××××", size:9999 };
■辞書を作成する
辞書として取り扱うための、Object オブジェクトを 1 つ作成します。
辞書用 Object オブジェクトを作成する
// 辞書を作成
var dictionary:Object = new Object();
■辞書に既にデータが存在するか調べる
指定したプロパティに、すでにデータが存在するか調べます。
配列アクセス演算子を使って、調べたいプロパティにアクセスします。
結果が、真であればデータが存在します。偽であればデータは存在しません。
辞書に既にデータが存在するか調べる
// 辞書を作成
var dictionary:Object = new Object();
// 検索したいアドレス情報
var url:String = "http://example.com/b.html";
// 辞書に既にデータが存在するか調べる
if(dictionary[url]){
trace("データは存在する");
}else{
trace("データは存在しない");
}
■辞書にデータを登録する
任意のプロパティに、データを登録します。
配列アクセス演算子を使って、任意のプロパティにデータを格納します。
辞書にデータを登録する
// 辞書を作成
var dictionary:Object = new Object();
// 管理したいデータ
var page_b:Object = { url:"http://example.com/b.html", title:"タイトルB", size:2621 };
// 辞書にデータが存在しないか調べる
if(!dictionary[page_b.url]){
// 辞書に新しいデータを登録する
dictionary[page_b.url] = page_b;
}
■辞書からデータを取得する
任意のプロパティから、データを取得します。
配列アクセス演算子を使って、任意のプロパティからデータを取得します。
null 値が得られる場合、データは存在しません。
辞書からデータを取得する
// 辞書を作成
var dictionary:Object = new Object();
// 管理したいデータ
var page_a:Object = { url:"http://example.com/a.html", title:"タイトルA", size:1310 };
var page_b:Object = { url:"http://example.com/b.html", title:"タイトルB", size:2621 };
var page_c:Object = { url:"http://example.com/c.html", title:"タイトルC", size:5242 };
// 辞書にデータを登録する
dictionary[page_a.url] = page_a;
dictionary[page_b.url] = page_b;
dictionary[page_c.url] = page_c;
// 検索したいアドレス情報
var url:String = "http://example.com/a.html";
// 辞書からデータを取得する
var page:Object = dictionary[url];
■辞書に登録したデータを削除する
任意のプロパティから、データを削除します。
delete 文を使って、任意のプロパティを削除します。
辞書に登録したデータを削除する
// 辞書を作成
var dictionary:Object = new Object();
// 管理したいデータ
var page_a:Object = { url:"http://example.com/a.html", title:"タイトルA", size:1310 };
var page_b:Object = { url:"http://example.com/b.html", title:"タイトルB", size:2621 };
var page_c:Object = { url:"http://example.com/c.html", title:"タイトルC", size:5242 };
// 辞書にデータを登録する
dictionary[page_a.url] = page_a;
dictionary[page_b.url] = page_b;
dictionary[page_c.url] = page_c;
// 検索したいアドレス情報
var url:String = "http://example.com/a.html";
// 辞書からデータを取得する
var page:Object = dictionary[url];
if(page){
// 辞書に登録したデータを削除する
delete dictionary[page.url];
}
オブジェクトを複製する
■オブジェクトを複製する
オブジェクトツリーを複製する関数です。
null、undefined、Boolean、Number、String、Array、Object 型のデータのみで構成する必要があります。
オブジェクトを複製する関数
// ------------------------------------------------------------
// オブジェクトを複製する関数
// ------------------------------------------------------------
function ObjectClone(obj:*):*{
if(typeof(obj) != "object") return obj;
var s:Object;
var o:Object;
var k:Object;
var r:Object = new (obj.constructor)();
var q:Array = new Array();
q.push({o:r,s:obj});
while(true){
k = q.pop();
if(!k) break;
o = k.o;
s = k.s;
for(k in s){
if(typeof(s[k]) == "object"){
if(s[k]){
o[k] = new (s[k].constructor)();
q.push({o:o[k],s:s[k]});
continue;
}
}
o[k] = s[k];
}
}
return r;
}
■使用例
オブジェクトツリーを複製する
// ------------------------------------------------------------
// オブジェクトを複製する関数
// ------------------------------------------------------------
function ObjectClone(obj:*):*{
if(typeof(obj) != "object") return obj;
var s:Object;
var o:Object;
var k:Object;
var r:Object = new (obj.constructor)();
var q:Array = new Array();
q.push({o:r,s:obj});
while(true){
k = q.pop();
if(!k) break;
o = k.o;
s = k.s;
for(k in s){
if(typeof(s[k]) == "object"){
if(s[k]){
o[k] = new (s[k].constructor)();
q.push({o:o[k],s:s[k]});
continue;
}
}
o[k] = s[k];
}
}
return r;
}
// ------------------------------------------------------------
// オブジェクトツリーを作成
// ------------------------------------------------------------
var obj:Object = {
aaa:{
count:123,
name:"テスト1",
result:false
},
bbb:{
count:456,
name:"テスト2",
result:true
},
ccc:{
count:789,
name:"テスト3",
param:{
ary:["a","b","c"],
name:"テスト4"
},
result:true
}
};
// ------------------------------------------------------------
// オブジェクトを複製
// ------------------------------------------------------------
var clone:Object = ObjectClone(obj);
// 出力テスト
trace(clone);
参照(リファレンスデータ)について
■リファレンス型について
すべてのオブジェクトは、リファレンス型に該当します。
リファレンス型は、複合的なデータ型です。
Array、Object、Function 型などは、すべてリファレンス型です。
リファレンスは、参照を意味します。
オブジェクトが、どのように参照として動作するか確認してみます。
■オブジェクトの参照を確認する
1.配列を作成してみる
配列を作成して、「変数 ary0 」に格納してみます。
配列を作成する
// 配列を作成する
var ary0:Array = ["a","b","c"];
2.配列を別の変数に代入してみる
「変数 ary0 」の中身を、「変数 ary1 」に代入してみます。
デバッガでは、以下のように表示されました。
「変数 ary0 」の配列が、「変数 ary1 」へとコピーされているように見えます。
作成した配列オブジェクトを別の変数に代入する
// 配列を作成する
var ary0:Array = ["a","b","c"];
// 配列を別の変数に代入する
var ary1:Array = ary0;
3.片方の変数から配列に書き込んでみる
次に、「変数 ary1 」から、配列の一部を書き換えてみます。
デバッガで確認すると、「変数 ary0 」と「変数 ary1 」の両方の配列が変化しました。
内部でどのような処理が行われているのでしょうか。
片方の変数から、配列の一部を変更する
// 配列を作成する
var ary0:Array = ["a","b","c"];
// 配列を別の変数に代入する
var ary1:Array = ary0;
// 変数 ary1 から、配列の 0 番地を変更する
ary1[0] = "d";
■オブジェクトの本体と参照について
先ほど、配列オブジェクトを作成して、「変数 ary0 」に格納しました。
配列を作成する
// 配列を作成する
var ary0:Array = ["a","b","c"];
オブジェクトを作成すると、オブジェクトの本体は、メモリ上のどこかに生成されます。
「変数 ary0 」には、「メモリ上のどこかに存在するオブジェクト本体」へアクセスするための、参照データが格納されています。
配列オブジェクト本体が、「変数 ary0 」に、直接格納される訳ではありません。
■オブジェクトの参照渡しについて
先ほど、「変数 ary0 」の中身を「変数 ary1 」に代入しました。
このとき、「変数 ary0 」の配列が、「変数 ary1 」へとコピーされた訳ではありません。
作成した配列オブジェクトを別の変数に代入する
// 配列を作成する
var ary0:Array = ["a","b","c"];
// 配列を別の変数に代入する
var ary1:Array = ary0;
「変数 ary0 」から「変数 ary1 」に渡したのは、「メモリ上のどこかに存在するオブジェクト本体」へアクセスするための、参照データです。
これにより、「変数 ary1 」からも、配列オブジェクト本体へアクセスできるようになります。
■参照渡しについて
リファレンス型のデータを、別の変数に代入する事を、参照渡しと言います。
参照渡しを利用すると、複数の変数から、1つのオブジェクト本体を共有できるようになります。
■不要になったオブジェクト本体を解放する
オブジェクト本体を、直接的に消滅させる命令はありません。
delete 文は、オブジェクトを破棄する命令ではありません。( C++ 使いの方は注意)
オブジェクトが不要になった場合、オブジェクトを格納している変数を、別の値で上書きします。
基本的には、null 値をセットします。
配列オブジェクトを解放する
// 配列を作成する
var ary0:Array = ["a","b","c"];
// 変数に null 値をセットする(配列オブジェクト本体にアクセスする手段が失われる)
ary0 = null;
オブジェクトの参照データを、別の値で上書きしたので、「メモリ上のどこかに存在するオブジェクト本体」へアクセスする手段が失われる事になります。
このとき、ガベージコレクションが、自動的に物理メモリから解放します。
■ null 値について
null 値とは、リファレンス型のデータが存在しない事を意味します。偽となります。
何らかのリファレンス型のデータが存在する場合は、真となります。
■ガベージコレクションについて
ガベージコレクションは、FlashPlayer から、自動的に、不定期に発生します。
ActionScript3.0 では、ガベージコレクションを手動的に動作させる事もできます。
詳しくは、こちらで解説しています。
ガベージコレクションは、不要になったオブジェクト本体が、物理メモリ上に存在するか調べます。
不要なオブジェクト本体があれば、物理メモリから解放します。
■不要なオブジェクトを解放するためには?
アクセスする手段が失われたオブジェクト本体は、不要なオブジェクトと判別されます。
オブジェクトが不要になった場合、参照をすべて断つ必要があります。
不要なオブジェクトが格納されている変数があれば、別の値で上書きします。
Object オブジェクトを解放する
// オブジェクトを作成する
var obj0:Object = {a:0,b:1,c:2};
// オブジェクトの参照を別の変数に渡す
var obj1:Object = obj0;
// 変数に null 値をセットする(この時点では、obj1 からオブジェクト本体にアクセスできる為、消滅しない)
obj0 = null;
// 変数に null 値をセットする(この時点で、オブジェクト本体にアクセスする手段が失われた為、ガベージコレクションの対象となる)
obj1 = null;
■メモリリークについて
オブジェクトが不要になった場合、オブジェクトの参照をすべて断つ必要があります。
1つでも参照が残っている場合、永遠に解放されずに物理メモリに残り続けます。
解放漏れの不備により、ゴミが物理メモリを占有し続ける事を、メモリリークといいます。
■エージングテスト
一連の処理を、自動的に、繰り返し実行されるようにして、長時間放置します。
FlashPlayer がクラッシュしていないか、エラーが発生していないか、物理メモリの使用量が増え続けていないか、異常な動作をしていないかを確認します。
長時間の稼動に耐えるほど、安心できます。
■表示オブジェクトの解放について
表示オブジェクトが、表示リストを通じてステージと繋がっている場合、自動的に解放される事はありません。
ステージから、表示リストを巡って、表示オブジェクトへアクセスできる為です。