目次

オブジェクトなJavaScriptの基礎講座

new演算子の謎

◆ はじめに

クッキーを勉強しようと「スタイルシート切り替え」のところのJCookie() を見ているうちに new演算子 の使い方に疑問を感じ、いろいろ(とほほサイト、OpenSpaceサイト)調べてもわからず、んじゅあ、自分でいろいろやるしかないかーって、いろいろテストをしてみました。

◆ そもそもnew演算子とは?

new演算子とは、短く云うと『新しいオブジェクトを作成』するためのものです。

new演算子は、普通以下の感じで、クラス『Charming( _age, _hair)』をコンストラクタ『Charming("13" , "short")』にして、インスタンス変数『Chaichan 』を作成します。

  function Charming( _age, _hair)
    {
      this.age = _age ;
      this.hair = _hair;
      return this;
    }
    var Chaichan = new Charming("13" , "short");

しかし、JCookie()は、以下の感じになっています。

function JCookie() {
	JCookie.data = new Array();
	JCookie.string = (document.cookie) ? document.cookie.split(';') : new Array() ;
	for (var i = 0; i != JCookie.string.length; i++) {
		JCookie.data[JCookie.string[i].split('=')[0].match(/[^ ].*/)]
			= JCookie.string[i].split('=')[1];
	}
	JCookie.put = function(name ,data ,limit) {
		var date = '';
		if (limit) {
			today = new Date();
			today.setTime(today.getTime()+1000*60*60*24*limit);
			date = ';expires='+today.toGMTString();
		}
		document.cookie = name+'='+data+';path=/'+date;
	}
}
new JCookie();

で、なにを疑問に思ったかというと以下の2つです。

  1. new JCookie();でコンストラクタしたオブジェクトの代入先のインスタンス変数がありません。
  2. JCookie.dataJCookie.stringのように、普通はthisのはずなのに、関数名のJCookieになっている。

◆ 6パターンのテスト

そこで、new演算子で代入先のインスタンス変数が『ある場合』と『ない場合』とインスタンス変数名とコンストラクタ名が『同じ場合』の3パターンを、クラス中でのオブジェクト名が『this』と『関数名』のそれぞれ場合で計6パターンのテストをしてみました。(たぶん、拙い文を理解するよりロジックを見たほうがわかりやすい...)

<script type="text/javascript">
//-----------------------------------------------------------ケース1
function testForNew_01(){
        this.method = function(name) {
                    return name;
        }
        this.property = "chaichan";
        testForNew_01.aaa="aaa";
} 
obj = new testForNew_01();
document.write("『this』でインスタンスが『ある場合』----------------------------------ケース1" + "<br>" );
document.write(obj.property + "<br>" );
document.write(obj.method("macha") + "<br>" );
document.write(obj.constructor + "<br>" );
document.write("objのプロパティ一覧----------------------------------ケース1" + "<br>" );
for( i in  obj) document.write( i +"<br>" );
document.write("testForNew_01のプロパティ一覧----------------------------------ケース1" + "<br>" );
for( i in  testForNew_01) document.write( i +"<br>" );

//-----------------------------------------------------------ケース2
function testForNew_02(){
        this.method = function(name) {
                    return name;
        }
        this.property = "chaichan";
} 
new testForNew_02();
document.write("『this』でインスタンスが『ない場合』----------------------------------ケース2" + "<br>" );
document.write(testForNew_02.property + "<br>" );
//document.write(testForNew_02.method("macha") + "<br>" );
document.write(testForNew_02.constructor + "<br>" );
for( i in  testForNew_03) document.write( i +"<br>" );


//------------------------------------------------------------ケース3
function testForNew_03(){
        this.method = function(name) {
                    return name;
        }
        this.property = "chaichan";
} 
testForNew_03 = new testForNew_03();
document.write("『this』でインスタンスが『同じ場合』----------------------------------ケース3" + "<br>" );
document.write(testForNew_03.property + "<br>" );
document.write(testForNew_03.method("macha") + "<br>" );
document.write(testForNew_03.constructor + "<br>" );
for( i in  testForNew_03) document.write( i +"<br>" );

//-------------------------------------------------------------ケース4
function testForNew_04(){
        testForNew_04.method = function(name) {
                    return name;
        }
        testForNew_04.property = "chaichan";
} 
obj = new testForNew_04();
document.write("『関数名』でインスタンスが『ある場合』----------------------------------ケース4" + "<br>" );
document.write(obj.property + "<br>" );
//document.write(obj.method("macha") + "<br>" );
document.write(obj.constructor + "<br>" );
for( i in  obj) document.write( i +"<br>" );

//-------------------------------------------------------------ケース5
function testForNew_05(){
        testForNew_05.method = function(name) {
                    return name;
        }
        testForNew_05.property = "chaichan";
} 
new testForNew_05();
document.write("『関数名』でインスタンスが『ない場合』----------------------------------ケース5" + "<br>" );
document.write(testForNew_05.property + "<br>" );
document.write(testForNew_05.method("macha") + "<br>" );
document.write(testForNew_05.constructor + "<br>" );
for( i in  testForNew_05) document.write( i +"<br>" );

//-------------------------------------------------------------ケース6
function testForNew_06(){
        testForNew_06.method = function(name) {
                    return name;
        }
        testForNew_06.property = "chaichan";
} 
testForNew_06 = new testForNew_06();
document.write("『関数名』でインスタンスが『同じ場合』----------------------------------ケース6" + "<br>" );
document.write(testForNew_06.property + "<br>" );
//document.write(testForNew_06.method("macha") + "<br>" );
document.write(testForNew_06.constructor + "<br>" );
for( i in  testForNew_06) document.write( i +"<br>" );

</script>

以下は、上記の実行結果です。

『this』でインスタンスが『ある場合』----------------------------------ケース1
chaichan
macha
function testForNew_01(){ this.method = function(name) { return name; } this.property = "chaichan"; testForNew_01.aaa="aaa"; }
objのプロパティ一覧----------------------------------ケース1
method
property
testForNew_01のプロパティ一覧----------------------------------ケース1
aaa
『this』でインスタンスが『ない場合』----------------------------------ケース2
undefined
function Function() { [native code] } 
『this』でインスタンスが『同じ場合』----------------------------------ケース3
chaichan
macha
function testForNew_03(){ this.method = function(name) { return name; } this.property = "chaichan"; }
method
property
『関数名』でインスタンスが『ある場合』----------------------------------ケース4
undefined
function testForNew_04(){ testForNew_04.method = function(name) { return name; } testForNew_04.property = "chaichan"; }
『関数名』でインスタンスが『ない場合』----------------------------------ケース5
chaichan
macha
function Function() { [native code] } 
method
property
『関数名』でインスタンスが『同じ場合』----------------------------------ケース6
undefined
function testForNew_06(){ testForNew_06.method = function(name) { return name; } testForNew_06.property = "chaichan"; }

◆ テスト総括

まず、クラスとオブジェクトとインスタンスを思い出してください(もちろんJavaScriptのケースで)。関数そのものは、クラスです。オブジェクトは、new演算子でメモリ上のどこかに作成されます。インスタンスは、インスタンス変数の中身そのものです。

で、代入先のインスタンス変数がない場合は、当然インスタンスはありません。しかし、newしたのですから、メモリ上にオブジェクトが作成されているはずです、そして、そのオブジェクトにアクセスするには、コンストラクタ名でできるようです。逆に云うとコンストラクタそのものが、オブジェクトになるような感じです。

また、コンストラクタ名とインスタンス名を一緒にするとインスタンス名が優先され、コンストラクタオブジェクト(実際はこんな呼び方はないかも)へのアクセスが出来なくなるみたいです。

◆ 結論

ではなぜ、JCookie()ようにインスタンスが無い使い方をするのかというと、オブジェクト名を任意にしたくない、つまり、固有のオブジェクト名にしたい時に有効のようです。

確かに、クッキーのI/O(入出力)等の機能が明確唯一の場合等の時は、固有オブジェクト(命名自作)にした方がプログラムが明確になると思います。

尚、今回は本題のクッキーについては、及ばなかったので、次回ということで...ではまた!

目次