javascriptクラス入門

最近javascriptを使う機会があったので、クラスの使い方、定石的な書き方などをまとめてみました。
まだまだ変化のある言語ですし、自分はCなど静的言語を中心にやってきたので、よいまとめサイトが見つからなかったんですよね。


参考書籍はこちら
パーフェクトJavaScript (PERFECT SERIES 4)

詳細まで書いているので、若干難しいですがjavascript関連の情報がひとつにまとまっているのですごく使いやすいです。
WebAPI,DOM,Event,jQueryと周辺技術やライブラリのことから、HTML5,Node.jsなど新しめの情報までまとまっています。


前半にクラス周りの事をまとめときました。

・クラスの作成

function Character(x,y){
    //この変数は外部からアクセス可能
	this.x = x;
	this.y = y;
	
	this.move = function ()
	{
		this.x += 1;
		this.y += 1;
		
		alert("x:"+this.x+"y:"+this.y);
	}	
}
var c1 = new Character(10,10);
c1.move();


・クラスの継承
クラスの継承にはprototypeを使う
prototypeの特徴
・すべての関数・オブジェクトprototypeという名前のプロパティを持つ
・自クラスにメソッドがなければプロトタイプで定義されているものを使用する
・prototypeは継承元クラスへの参照のようなもの

function Person(x,y){
	this.x = x;
	this.y = y;
	
	this.walk = function()
	{
		this.x += 1;
		this.y += 1;
		alert("歩きます。("+this.x+","+this.y+")");
	}
}

Person.prototype.dash = function ()
{
	this.x += 10;
	this.y += 10;
	alert("走ります。("+this.x+","+this.y+")");
}


person1 = new Person(0,0);
//自クラスにメソッドがなければプロトタイプで定義されているものを使用する(プロトタイプチェーン)
person1.walk();
person1.dash();


クロージャ
平たく言うと上にかいたクラスとほぼ同じ機能を作れます。
書き方の違いはthisを使わないこと。使用する機能を戻り値として返すこと。newを使わないことです。
関数内で関数を宣言することで使えます。

function Person(x,y){
    //この変数は外部からアクセス不可
	var x =x;
	var y =y;
	
	
	function walk()
	{
		x += 1;
		y += 1;
		alert("歩きます。("+x+","+y+")");
	}
	
	return walk;
}

var closure = Person(0,0);
closure();
closure();
closure();

エンクロージャクロージャにおいて、中の関数を囲んでいる外側の関数のこと(ここだとPerson)
レキシカル変数:エンクロージャのローカル変数のこと(ここだとx,y)
このあたりの用語も時々使われてます。


クロージャとクラス
自分の理解を書いておきます。間違っていたら指摘お願いします。
●クラス
javascriptではオブジェクトによってクラスを実現できる。thisで追加された変数はプロパティとして、
オブジェクトのインスタンスに追加される。オブジェクトのメンバの参照時は自分のメンバを見て存在しなければ、prototypeのメンバを参照し解決する
prototypeで継承を実装でき、同じオブジェクトを大量に作るときなどにも便利
http://builder.japan.zdnet.com/script/sp_javascript-kickstart-2007/20369263/1/
(詳細はthis参照、プロトタイプチェーン)

クロージャ
クロージャーは状態を持つ関数、変数はvarで宣言し、ローカル変数となるため外部からアクセス出来ない。
コールバック関数を作るときなどに便利。
(詳細はCallオブジェクト、スコープチェーン)




・定石的な書き方
1.オブジェクトの初期化
comが初期化されていればそれを使い、なければ空オブジェクトで初期化する。

//オブジェクトの初期化
var com = com || {};
//変数の初期化にもつかえる
var a = a || 256;

2.名前空間的な物
オブジェクトのプロパティを名前空間のように使い、プロパティ、メソッドの重複を防ぎます。

var com = com || {};
if(!com.mydomain) com.mydomain = {}; 
if(!com.mydomain.myproj) com.mydomain.myproj ={};
if(!com.mydomain.myproj.myfunc) com.mydomain.myproj.myfunc = {};

3.無名関数、クロージャーでグローバルの汚染を防ぐ

(function() {
//このなかは関数スコープなのでグローバルを汚染しない
})();

名前空間的なもの(グローバルにあるもの)を無名関数からアクセスして、
うまくアクセスの制限をかける。

var com = com || {};
if(!com.mydomain) com.mydomain = {}; 
if(!com.mydomain.myproj) com.mydomain.myproj ={};
if(!com.mydomain.myproj.myfunc) com.mydomain.myproj.myfunc = {};

//以下の中ではグローバルを汚さない
(function() {
com.mydomain.myproj.myfunc.action= (function(){
alert("hoge");
});
})();

//メソッド呼び出し
com.mydomain.myproj.myfunc.action();


※以下基本的な事※



・変数・定数
varを使って宣言する。varは無くても使えるけどスコープはグローバルになる。
定数はconst

var a;
//定数
const PI =3.141592653589;
a=PI;
alert(a);

変数の初期値はundefined


・変数のスコープ
グローバルスコープ、関数スコープがある。ブロックスコープはなし。

function func1()
{
	var x;
	x="func1";
	alert(x);
}

function func2()
{
	var y;
	y="func2";
	alert(x);
	//関数スコープなのでここでアクセスできない
	alert(y);
}

・オブジェクト
連想配列のようなもの。
関数を値として保存できる。クラスを作成するときに使えたりとjavascriptの重要機能の一つ

var obj = {a:1,b:2,c:3};
obj.a;
obj['a']
//新規プロパティも簡単に追加できる
obj.d = 4;
//関数もプロパティにできる
obj.add = function(a,b){ return a + b };
alert(obj.add(1,2));
//オブジェクトの作成方法
var obj2 = new Object();
//空オブジェクトで作成
var obj3 = {};

・配列
実態はArrayクラスとのこと。
使い方は他の言語と同じ。

var arr = [1,'hoge',2];

・型
文字列、数値、ブーリアン,null,undefined、オブジェクト型と、ラッパークラスがある。
基本型は値が渡され、オブジェクトは参照(ポインタ)が渡される。

・引数の渡し方
デフォルト引数のようなことをできる

function len(x,y){
	return Math.sqrt(x*x+y*y);
}

function len2(pos){
	pos = pos || { x:0,y:1};
	return Math.sqrt(pos.x*pos.x+pos.y*pos.y);
}

参考サイト
クラス関連について調査した時に見つけたサイト

・クラスのいろいろな書き方
http://d.hatena.ne.jp/amachang/20060516/1147778600
・varとthisの違い
http://d.hatena.ne.jp/bingo_nakanishi_perl/20090529/1243605991
・thisの実行時解釈
http://d.hatena.ne.jp/amachang/20070917/1190015123
javascriptオブジェクト指向についてのtips
http://ichitcltk.hustle.ne.jp/gudon/modules/pico_rd/index.php?content_id=32
・スコープチェーン,callオブジェクトについて
http://d.hatena.ne.jp/otosohamirin/20100519/1274258237
クロージャを使ったペイントソフト
http://0xcc.net/blog/archives/000040.html
・関数呼び出しとnewの関連
http://liosk.blog103.fc2.com/blog-entry-32.html
・プロトタイプチェーン
http://d.hatena.ne.jp/amachang/20060406/1144339901
・オブジェクト、コンストラクタ、プロトタイプ、スコープ
http://d.hatena.ne.jp/qnzm/20081014/1223934778
jQueryクロージャーを有効活用
http://dqn.sakusakutto.jp/2012/02/javascript_13.html
クロージャとprototypeの実行効率の違い
http://d.hatena.ne.jp/anatoo/20090602/1243881722
・タイプ・クラス・プロトタイプの考え方
http://blog.livedoor.jp/dankogai/archives/51033584.html
・javascriptPrototype注意点
http://blog.livedoor.jp/dankogai/archives/50808279.html
・Prototype的継承?
http://blog.livedoor.jp/dankogai/archives/50662064.html
名前空間などソースを使いやすく書く方法
http://archiva.jp/web/javascript/writing_style.html
jQueryのextend 初期値をもたせたりできる
http://d.hatena.ne.jp/nitoyon/20110324/jQuery_extend_mania
javascriptのクラスの作成(長文)
http://mahoris-program.blog.so-net.ne.jp/JavaScript_Class_Create_1
javascriptカプセル化
http://yabooo.org/archives/53
・無名関数のいろんなパターン
http://blog.livedoor.jp/eeu/archives/55310188.html
・無名関数の考え方
http://d.hatena.ne.jp/amachang/20080208/1202448348
クロージャーを使ったクラスと継承
http://revengejs.blog69.fc2.com/blog-entry-10.html