おれの技術日記

元はJava+SQLがメインのエンジニア、フロントエンドは軽くかじった程度で苦手。最近忘れっぽいので覚えたことをいろいろメモするためにブログ開始。

JavaScript再入門4 - call, apply, bind

JavaScript再入門3 - thisは何を意味するか - おれの技術日記の続き。

例によってこちらにお世話になります。
最強オブジェクト指向言語 JavaScript 再入門!

7. call/applyを使ってthisをコントロールしつつ関数をコールする。

前回のブログの中で、thisというのはコンテキストによって可変で関数実行時に決定されるということがわかった。
このthisをコントロールしつつ関数を呼び出すのがcallとapply。この二つは記述方式こそ違うものの、やっていることは本質的に同じ。
・関数内でのthisが何か
・呼び出すときの引数は何か
というのを指定しつつその関数を実行する。

callとapplyは以下のようなシンタックスで使用される。ここでobjectは関数内でのthisにあたり、arg1以降は関数を呼び出す時に渡される引数となる。call関数は可変長引数であるのに対して、apply関数はArrayを第二引数にとる。

call(object, arg1 ,arg2...)
apply(object, [arg1,arg2,...])

例えば以下のようなコードの場合、func1は3回呼び出され全く同じ結果となる。

function func1(){
    console.log("123");
}
func1();//123が表示される
func1.call();//123が表示される
func1.apply();//123が表示される

以下のようなコードの場合、最初のコールではthisがwindowオブジェクトになってしまうがwindowオブジェクトにname属性は存在しないためthis.nameは空になる(undefinedにならないのはなんでだろう・・・)。一方でcall・applyを通じてコールする時に引数にobjを渡しているので、this=objとなりname属性の値がログ出力される。

function func1(){
	console.log("log:" + this.name);
}
var obj = {
	name:"obj_name",
}
func1();//log:だけがコンソール出力される
func1.call(obj);//log:obj_nameがコンソール出力される
func1.apply(obj);//log:obj_nameがコンソール出力される

これはfunc1に引数が存在する場合の呼び出し方。callでもapplyでも、可変長引数なのか配列を渡すのかの違いだけで結果は一緒。

function func1(param1, param2){
	console.log("log:" + this.name + ":" + param1 + param2);
}
var obj = {
	name:"obj_name",
}
func1.call(obj, "this is ", "test");//log:obj_name:this is testがコンソール出力される
func1.apply(obj, ["this is ", "test"]);//log:obj_name:this is testがコンソール出力される

8. bindを使って関数内のthisを固定化する。

通常は関数とオブジェクトには何の関連もなく、関数が呼び出されたときにその状況によってthisの値が決定される。しかしbind関数を使えば実際の関数呼び出しの前にthisを固定化することができる。

以下のコードではfunc2はobjとbindされているためthisの値が存在するが、func1はbindされていないのでthis.nameが空となる。

function func1(param1, param2){
	console.log("log:" + this.name + ":" + param1 + param2);
}
var obj = {
	name:"obj_name",
}

var func2 = func1.bind(obj);
func2("this is ", "test");//log:obj_name:this is testがコンソール出力される
func1("this is ", "test");//log::this is testがコンソール出力される

という仕様は理解したものの、実際どういうところで使うんだろう・・・・大規模なJavaScriptでの開発とかやってみたい。

依然として今後の課題

  1. Apply関数って何?→thisをコントロールするためのものらしい
  2. (function() {})();とかいう記法→即時関数というらしい
  3. thisのスコープの考え方