2007/11/30
javascriptを初めて学ぶ人についてのおさらい。その1
僕にも教える人ができた(? というか人にモノを教える立場)になったので、とりあえず、最近はもっぱらjavascriptを教えています。
もともとCやJavaなどについてはある程度の知識がある人なので、それを少しjs的な意味で、関数言語的な教えをやっている最中のメモ
変数って何ですか?変数って値もしくは式そのものに利便的な名前をつけているものです
次のhogeとfooは値をいれる箱ではなく、値そのものに別名(もしくは分かりやすい名称)を割り当てているだけに過ぎませんよ。
var hoge = 1; var foo = [1, 2, 3]; alert(hoge + 1); // 2 alert(foo[0]); // 1 alert(1 + 1); // 2 alert([1, 2, 3][0]); // 1
つまり、関数自体を変数に代入する事ができます。(functionとは特別な呼び名ではなく、[](Array)や{}(Object)のような簡単な型名の一つです)
関数はグローバルに置かれる必要はなく、関数さえも変数の一つとして扱えます。
var _eval = eval; var _alert = window.alert; var _func = Function; var lambda = function (){ alert("hoge"); }; alert(typeof _eval); // function alert(typeof _alert); // function alert(typeof _func); // function alert(typeof lambda); // function
"("から")" は実行するための目印です。引数はその中に書く事ができます。applyやcallという別名もあります。
関数を受け取った変数であっても、()を使う事で呼び出しを行うことができます。
var test1 = function (){ alert("hoge"); }; var test2 = function (){ return function(){ alert("foo"); }; }; var test3 = function (k){ return k(); }; test1(); // hoge var a = test2(); a(); // foo test2()() // foo test3(test2)(); // foo var b = test2(); test3(b); // foo
thisは呼び出された変数を保持しているオブジェクトで変化します
thisの参照は呼び出された関数を保持しているモノによって変化します。
var say = function (){ alert(this.message); }; var hoge = { message: 'hoge' }; var foo = { message: 'foo' }; hoge.say = say; foo.say = say; hoge.say(); // hoge foo.say(); // foo
これを分かりやすくapplyとかcallとかって別名で呼ぶ事もあります。
var say = function (){ alert(this.message); }; var hoge = { message: 'hoge' }; var foo = { message: 'foo' }; say.apply(hoge, null); // hoge say.call(foo, null); // foo
でも、applyやcallは委譲を行うためにも使えます
applyはthisの参照先を変更できるので、委譲するときにも使います。
var Main = { hello: function (){ alert(this.world()); } }; var hoge = { world: function (){ return 'hoge world'; } }; var foo = { world: function (){ return 'foo world'; } }; var hello = Main.hello; hello.apply(hoge, null); // hoge world hello.apply(foo, null); // foo world
参照とはなんでしょうか?それは変数を触れる事ができる範囲の定義です
変数で宣言したものには、参照先が決まっています。その参照の範囲はスコープとも呼びます。
var a = 1; var hoge = function (lambda){ alert(a); // undefined; lambda(); // 1 var a = 2; lambda(); // 1 alert(a); // 2; }; var foo = function (){ alert(a); }; hoge(foo); alert(a); // 1;
引数の変数にも参照はあります。
var hoge = function(arg0, arg1){ return function (k){ alert(arg0 + arg1); // 'helloworld' k(); }; }; var foo = hoge('hello', 'world'); foo(function (){ alert(typeof arg0); // undefined alert(typeof arg1); // undefined });
参照できる値そのものを渡すことも可能です。
var hoge = function(arg0, arg1){ return function (k){ return function (){ return k(arg0, arg1); } }; }; var foo = hoge('hello', 'world'); var bar = foo(function (arg0, arg1){ alert(arg0 + arg1); // 'helloworld' }); bar();
こうした動きはクロージャやレキシカルスコープという呼び名があり、うまく使うと便利です
var createCounter = function (){ var count = 0; return function (){ return count++; }; }; var counter = createCounter(); alert(counter()); // 0 alert(counter()); // 1 alert(counter()); // 2 alert(counter()); // 3
メソッドとは何でしょうか?それは関数の参照を持っているだけのモノです。
メソッドの呼び出しは参照の違いでしかないです。
var message = 'this is global'; var Hoge = function (){ var message = 'this is hoge'; this.say = function (){ return message; } }; var hoge = new Hoge; alert(hoge.say()); // this is hoge var Foo = function (){}; var foo = new Foo; foo.say = hoge.say; alert(foo.say()); // this is hoge var Bar = function (){ this.say = function (){ return message; } }; var bar = new Bar; alert(bar.say()); // this is global
コンストラクタとは何でしょうか?それはthisの参照を明示的に指定しているだけの関数です。
thisで呼び出すには、オブジェクトにしないといけないです。いわゆるインスタンス化です。それはコンストラクタを通して行われます。
ref - ハタさんのブログ : javascriptのコンストラクタとか
var Hoge = function (msg){ this.message = msg + ' is Hoge'; return this.message; }; var hoge1 = Hoge('hello'); alert(hoge1); // hello is Hoge alert(hoge1.message); // undefined var hoge2 = new Hoge('world'); alert(hoge2); // [object Object] alert(hoge2.message); // world is Hoge var Foo = function(msg){ this.toString = function (){ return msg + ' is Foo'; } return msg; }; var foo1 = Foo('abc'); alert(foo1); // abc alert(foo1.toString()); // abc var foo2 = new Foo('def'); alert(foo2); // def is Foo alert(foo2.toString()); // def is Foo
次のString関数はコンストラクタの呼び出しと関数の呼び出しがあります。
var message1 = String('message one'); var message2 = new String('message two'); alert(message1); // message one alert(message2); // message two alert(typeof message1); // string alert(typeof message2); // object
おさらい。その1
ということで、その1のおさらいとしては、関数と変数と参照になります。
thisは単なるスコープで、参照はthisが持っていますし、変数の参照先によって違う値を持てます。
また、変数は値もしくは式の別名で、それもまた参照を持てるということがわかりました(?)
というか、↓に書かれている事が関数型言語について全てを物語っているのですが、やはり少しづつ学んで貰うのがベストかと。
via - 関数型言語(プログラミング言語Scheme, Haskellなど)を勉強しようと思っています。 初心者にも関数型言語のメリットや考えかたがスラスラ分かる勉強の材料を教えてくださ.. - 人力検索はてな
ECMAScript 特有のプロトタイプや可変引数、クロージャについてもっとkwskや高階関数、applyとかsetTimeout、イベント系、 DOM系については順を追って、その2、その3へ。
つづく
Trackback
No Trackbacks
Track from Your Website
http://blog.xole.net/trackback/tb.php?id=640

5 Comments
Re: javascriptを初めて学ぶ人についてのおさらい。その1
ものすごーく分かりやすいです!!
From : くみこ @ 2007-12-01 06:40:16 編集
Re: javascriptを初めて学ぶ人についてのおさらい。その1
すごく分かりやすいです!
ただ…
var hoge = function (lambda){
alert(a); // undefined;
lambda(); // 1
var a = 2;
lambda(); // 1
alert(a); // 2;
};
この『lambda(); // 1』ってところが分かりません…(T_T)
何故1が返るんでしょうか?
From : hoge @ 2007-12-01 11:06:28 編集
Re: javascriptを初めて学ぶ人についてのおさらい。その1
>くみこさん
ありがとうございます。励みになります!
>hogeさん
それは、以下のようにすれば分かりますでしょうか?
lambda()ではhogeのスコープではなく、その外側のスコープについて変数aの評価をしていると言えます。
var a = 1;
var hoge = function (){
alert(a); // undefined;
var a = 2;
alert(a); // 2;
};
var foo = function (){
alert(a); // 1
};
hoge();
foo();
また、hoge()内で、aがundefinedになってしまうのは、hoge内で、既に宣言済み変数aについて定義し直したためといえます。
関数hogeは次のようにも書き換える事ができます。
var a = 1;
var hoge = function (){
var a;
alert(a); // undefined;
a = 2;
alert(a); // 2;
};
hoge();
ということで、関数内にあるスコープと、その外側で宣言されたスコープは別の場所に参照されるということになります。
From : ハタ @ 2007-12-01 23:17:09 編集
Re: javascriptを初めて学ぶ人についてのおさらい。その1
hogeさん同様にlambda()がわからなかったけど、それも理解できました。
まじわっかりやすいです!その2が超楽しみです、応援してます!
From : q @ 2007-12-02 03:33:10 編集
理解できました♪
スコープ以前に引数lambdaの意味が分かっていませんでした。
この場合はlamda = fooなんですね。(要するにlamda() = foo())
引数(変数?)に関数が代入できるっていうのが、
感覚的にしか理解できてませんでした…
> aがundefinedになってしまうのは、hoge内で、既に宣言済み変数aについて定義し直したためといえます。
あと、これは驚きました。
自分だけかも知れませんがJavascriptってスコープ領域がかなり分かり辛いです…
でも今回のエントリでJavascriptが随分読めるようになりました♪
ありがとうございました。
From : hoge @ 2007-12-02 12:54:16 編集