-
ID:bdvpk5 さんの質問

すいません!javascriptを学び始めのものなのですが、以下のjavascriptコードを一行一行説明して頂けないでしょうか??

急ぎでjavascriptでコーディング出来るようになる必要があり、かなり焦ってます(汗)今日にはコーディングスタートしないといけない状況でやばいです。。。

全部でなくても勿論構いませんので、可能な範囲でお願い出来ると大変助かります!!

自分でも随時、わかるところ、わかったところはコメントを付けてみます。

※「投稿内容は3000文字以内で入力してください。」と表示されてしまったので、自分でわかったところや分かった気がするようなところはコメント欄に書き込んで行きますm(_ _)m
.
.

(function(exports) {

var TodoModel = function() {
this.contents = ’’;
this.listeners = [];
}
.
.

TodoModel.prototype.setContents = function(contents) {
if (this.contents !== contents) {
this.contents = contents;
this.notifyListeners();
}
}
.
.

TodoModel.prototype.bindToInput = function(input) {
var _this = this;

var eventHandler = function(e) {
if (typeof(e.target.value) != ’undefined’) {
_this.setContents(e.target.value);
}
};

input.addEventListener(’keyup’, eventHandler);
input.addEventListener(’change’, eventHandler);
}
.
.

TodoModel.prototype.bindToView = function(view) {
this.addListener(function(model) {
if (view.setValue) {
view.setValue(model.contents);
} else {
view.innerText=model.contents;
}
});
}

.
.

TodoModel.prototype.addListener = function(listener) {
this.listeners.push(listener);
}

.
.

TodoModel.prototype.notifyListeners = function() {
var this_ = this;
this.listeners.forEach(function(listener) {
listener(this_);
});
}

.
.

exports.TodoModel = TodoModel;

})(window);

.
.

window.addEventListener(’DOMContentLoaded’, function() {

var model = new TodoModel();
var newTodo = document.getElementById(’newTodo’);
var todoText = document.getElementById(’todoText’);

model.bindToView(todoText);
model.bindToInput(newTodo);

})

-----------------------------------------
参考になりそうなリンク
-----------------------------------------
http://d.hatena.ne.jp/graySpace/20110703/1309660990

http://hitsujiwool.tumblr.com/post/25562292144/module-patterns-of-javascript

http://lostlinksearch.net/blog/2012/10/javascript-%E3%81%AE%E7%84%A1%E5%90%8D%E9%96%A2%E6%95%B0%E3%81%AE%E4%B8%AD%E3%81%AEthis%E3%81%AF%E4%BD%95%E3%82%92%E6%8C%87%E3%81%99%E3%81%8B/

http://qiita.com/takeharu/items/9935ce476a17d6258e27
-----------------------------------------

みんなの回答 22 件

ID:bdvpk5 さんの回答

  1. (function(exports) {

中略

exports.TodoModel = TodoModel;

})(window);

即時関数というやつで、引数に渡したオブジェクトに
即時関数内で作成したオブジェクトを追加してあげる。
この場合はwindowオブジェクトのプロパティー(?)に
即時関数内のTodoModelを入れて上げている。

ID:bdvpk5

"ブラウザで動作する JavaScript では、トップレベルオブジェクト(window)を省略できます。"って検索したら書いてあった。

なので、この後に設定するプロパティーやメソッドを呼ぶ際にはwindowはつけなくてもOKみたい。

ID:0X0MXF

即時関数の実行時の引数にwindowを渡してるので、この場合exports = windowとしてるのと同じですね。

ID:bdvpk5

了解です!ここは理解できました!

ID:bdvpk5 さんの回答

  1. var TodoModel = function() {
    this.contents = ’’;
    this.listeners = [];
    }

TodoModelオブジェクトのインスタンスプロパティーとして
contentsとlistenersを作る。

この書き方はコンストラクタらしい。new TodoModel()みたいにしてインスタンス化する。

ID:bdvpk5

contentsには後で出て来る[e.target.value]がsetされる模様。

ID:bdvpk5

e.targetは、"その Event オブジェクトには発火元となった要素を target プロパティとして保持しています." らしい。イベントの発火もととなった要素のvalueってのをcontentsにsetするみたい。valueってどんな値になるんだろう。

ID:bdvpk5

わかった。valueってのは<input value="xxx">のxxxのところだ。

ID:bdvpk5 さんの回答

  1. TodoModel.prototype.setContents = function(contents) {
    if (this.contents !== contents) {
    this.contents = contents;
    this.notifyListeners();
    }

これは、TodoModel.setContents(contents);みたいに
メソッドを後で呼べるようになるのか??

そうだとしたら、インスタンス化されたTodoModelオブジェクトのcontentsプロパティーの値と、setContentsメソッドの引数に渡された値が違う場合のみ、if文内を実行する。インスタンスのcontensプロパティーに引数に渡された値を入れてあげて、その後にTodoModelオブジェクトのnotifyListeners()を実行する。どこでnotifyListeners()なんて作られていたっけ??

ID:bdvpk5

setContents()はbindToInput()の中で呼ばれるやつ。

ID:0X0MXF

とりあえずこの場合はconsole.log(this)ってやってみて中身みたほうがいいね。

ID:bdvpk5

そうですね。わからない時はlogを出して確認すれば良いんですよね!なるほどです!

ID:bdvpk5 さんの回答

(4)

TodoModel.prototype.bindToInput = function(input) {
var _this = this;
var eventHandler = function(e) {
if (typeof(e.target.value) != ’undefined’) {
_this.setContents(e.target.value);
}
};
input.addEventListener(’keyup’, eventHandler);
input.addEventListener(’change’, eventHandler);
}

「var _this = this」ってのは何だろう。右側のthisは何を指しているのか?

_this.setContents()としているから、この時点でのthisはインスタンス自体を指しているっぽい。

下の2行でkeyupとchangeというイベントに上で定義したeventHandlerメソッドを紐づけている。

イベントが呼ばれると(e)のところにイベント関連の情報が自動で渡って、そこから取り出した値をsetContents()でインスタンスのcontentsプロパティーにセットしているっぽい。

ID:0X0MXF

thisを一旦退避してるだけだよ。setInterval使う時とかに元のthis使いたい場合によくする

ID:bdvpk5

ありがとうございます!

_this.setContents(e.target.value);の_thisってのをthisにしてしまうと問題が起きるのでしょうか?

ID:0X0MXF

TodoModel.prototype.bindToInputとeventHandlerのthisが違う場合は起きますよ。

ID:bdvpk5

引数inputに渡した要素に対して、イベントを設定してる。それで、イベントが起きた時に発火させるメソッドがeventHanderっていう変数にはいって、その変数にいれる関数がその上で定義されている。

つまり、やってることとしては、bindToInput()の引数に渡した要素に対してイベントを設定して、そのイベントが起きるとイベント発火元要素のvalue値をインスタンスのcontentsにセットしているということ。

ID:bdvpk5

ありがとうございます。「event this」で今ぐぐってみてます!
www.sitepoint.com/javascript-this-event-handlers/
とりあえずこの記事読みます。

ID:bdvpk5

eventHandlerメソッドの中で_thisにしているのは、thisにしてしまうと、イベントの発火もとのオブジェクトがthisとなってしまうということなのでしょうか??それを回避するために、インスタンスをしめすthisを一旦、
_thisに入れてあげているのでしょうか???

ID:0X0MXF

そういう事ですね。 何がこのイベントを発火させたのかでthisの値が変わってしまうので、_thisに入れてるってことです。

ID:bdvpk5

なーーーーーるほどーーー!!すっごいややこしいですね、コレ!ありがとうございました!!

ID:bdvpk5 さんの回答

(5)

TodoModel.prototype.addListener = function(listener) {
this.listeners.push(listener);
}

一つ上のブロックを飛ばして、さきにこっちにコメント付け。

インスタンス.addListener(listener)を呼ぶとインスタンスプロパティーのlisternesに引数に渡した値が追加されるっぽい。

ID:bdvpk5

addLister()はbindToView()の中で呼ばれるプライベートな関数。

ID:bdvpk5

addListener(listener)の引数には、bindToViewの中で関数を渡してる。つまり、this.listenersの配列の中にイベントが発生したときに呼ぶ関数を登録するって処理をしてるっぽい。

ID:bdvpk5 さんの回答

(6)

TodoModel.prototype.bindToView = function(view) {
this.addListener(function(model) {
if (view.setValue) {
view.setValue(model.contents);
} else {
view.innerText=model.contents;
}
});
}

インスタンス.bindToView(view)を呼ぶと、インスタンスメソッドのインスタンス.addListenerを実行。

addLister()の引数が関数になっているのは何だろう。。。

しかも、その引数のなかの関数にも引数modelがあるけど、どこからこのmodelの引数は渡ってくるのか??

addLister()の引数内の関数では、bindToViewの引数に渡されたものにsetValueがあるかどうかをチェックして、ある場合はそのメソッドを引数model.contentsをわたして実行。

無い場合は、bindToViewの引数に渡したviewのinnerTextにmodel.contentsの内容をいれる。

this.contentsってのを最初の方で定義してたけど、それがmodel.contentsに呼応するかたちになるのか?

ID:bdvpk5

bindToView()を実行すると、中で呼ばれるaddListener()によって、addListener()の引数に渡したイベントハンドラー関数をインスタンスのlisteners配列に登録するっていう処理をしていることは理解した。

ID:bdvpk5

どうやって、addListerer(model)のmodelっていう引数が渡ってくるのかがいまいちよくわからない!!

たぶん、ここだけあとわからないんだと思われる。

どなたがお助けください〜〜〜〜〜〜>_<

ID:bdvpk5

全体的に一通りざっと理解はしたけど、ここのaddListener(model)ってところがいまいちわからない。ここをどうにか理解したい。

ID:bdvpk5

model.contentsって出て来るくらいだから、引数に渡って来ているmodelってのはインスタンス自身のような気がする。でも、なぜ、引数に渡ってくるのか。どういう仕組みなんだ。

ID:bdvpk5

あ、わかった!!

notifyListeners()の中で、
this.listeners.forEach(function(listener) {
listener(this_);
が呼ばれてるから、addListenner(model)のmodelっていう引数はthisってことか!!

おっけーーーーーーー!!!!

ID:iVhlep さんの回答

頑張ってください!応援しています。

ID:bdvpk5

ありがとうございます!!ちょっと急いでjavascriptを理解してコーディングできるようにならないとマズい状況なので、やばいです!!

ID:bdvpk5 さんの回答

(7)

TodoModel.prototype.notifyListeners = function() {
var this_ = this;
this.listeners.forEach(function(listener) {
listener(this_);
});

また、thisが出てきた。ちょっとちゃんと理解しないとまずいっぽい。

forEachっていうメソッドがたぶん、配列オブジェクトに備わっているっぽい。
forEachの引数にある関数がよくわからない。

さっきも引数に関数が入ってたけど、コールバックかなにかなのか。

引数のlistenerはどこから値が渡ってくるのか?

とりあえず、listenersに含まれるものをforEachして、listener(this_)って感じでループさせてるみたい。

インスタンス自体に引数に渡したlistenerっていうメソッドを読んであげてるらしい。

ID:bdvpk5

this.listenersのthisはなんで「this_」にしないんだろう???

よくわからん!それと、forEachの中の引数の関数って何なのだろう。。。

ID:bdvpk5

array1.forEach(callbackfn[, thisArg])

コールバックらしい。

ID:bdvpk5

function callbackfn(value, index, array1)

第一引数valueは配列の各要素の値みたい。つまり、this.listenersの配列に登録したイベントハンドラ関数が第一引数に渡って来ている。

ID:bdvpk5

つまり、listener(this_);はthis.listenersに登録したイベントハンドラ関数で引数にインスタンス自身を渡して実行しているようなのだけど、bindToView の中のaddListener()の中で行われていることがいまいち理解できてない。

ID:bdvpk5 さんの回答

(8)

exports.TodoModel = TodoModel;

ここは単純に一番外にあるコンストラクタ関数の引数に渡したwindowオブジェクトのプロパティー(?)であるTodoModelに関数内で作ったTodoModelをいれてあげているだけ。

ID:bdvpk5 さんの回答

(9)

window.addEventListener(’DOMContentLoaded’, function() {
var model = new TodoModel();
var todoText = document.getElementById(’todoText’);
var newTodo = document.getElementById(’newTodo’);
model.bindToView(todoText);
model.bindToInput(newTodo);
})

DOMがロードされた時のイベント設定をしている。

さっき定義したTodoModelをインスタンス化して変数modelに入れてる。

HTMLドキュメントからIDがtodoTextってのとnewTodoってのを、それぞれ変数にいれてあげてる。

最後の2行がちょっと今までに出てきたやつが絡んで来るから、理解するのが大変。

ちょっと考える!

ID:nIdLSF さんの回答

がんばれー!

ID:bdvpk5

ありがとうございます!がんばります!

ID:0X0MXF さんの回答

Githubかなんかのコードレビューできるやつでやったらいいのに

ID:bdvpk5

githubって使った事ないんです!ちょっとまだWeb経験少ないので引き出し少ないです。

ID:75L5Qr さんの回答

優秀だなぁ。俺にはさっぱりだ。

ID:bdvpk5

いえいえ、jsほぼ初心者なので、火事場の糞力みたいなもので集中して今無理してます!

ID:g45uaY さんの回答

がんばってください応援してます。

ID:bdvpk5

ありがとうございます!

ID:WtAOIA さんの回答

とりあえず、thisはあまり気にしなくてよいと思うよ。
そこからの理解だとかなり深くなるので。
閉じられたオブジェクトの中ではスコープが変わるので、thisの参照先も変わるくらいに思っていればいいんじゃないかな。そうなるとオブジェクトって何って話になるので更に深くなるがw

ID:bdvpk5

ありがとうございます。jsはややこしいですね!!

this.addListener(function(model) {
if (view.setValue) {
view.setValue(model.contents);
} else {
view.innerText=model.contents;
}
});

すいません。ここの引数のmodelっていうのはどこから渡ってくるのかわかりますでしょうか??

ID:bdvpk5

自己解決しました!

ID:bdvpk5 さんの回答

ありがとうございました!!

一先ず、このコードは理解出来ました!

コメントで励まし頂いた方、また、回答頂いた方ありがとうございました!!

もう少し、jsの基本的なところを2時間だけ時間を決めて集中してざっと把握して、そのあと、徹夜覚悟でjsコーディングの仕事開始します(汗)

ID:DIuAJQ さんの回答

すごいなー。

jsしばらく勉強してるのに、自分には分からない…

頭の出来の違いに凹んだ。

ID:bdvpk5

いえいえ、まだ前々理解が浅いです!当たり前ですが仕事に使えるレベルに達するまで時間はかかりそうですね。1日、2日で使いこなせるようなものではjavascriptはないですね。

ID:wHBSjG さんの回答

久しぶりに見た良いスレ。

ID:bdvpk5

ありがとうございます。ちょっと無駄スレって言われるかと正直思ってましたが意外なリアクションが嬉しかったです。

ID:mrTAzC さんの回答

夏休みは昨日までだぞ。

ID:iVhlep

仕事というより、課題な気がしてきた。

ID:bdvpk5

ほんとですね!今日から9月ですね!!

ID:DQNje5

仕事としてヘルプ依頼する選択肢はないのかしら???

ID:DQNje5

おっとマジレスは野暮でしたね…

ID:bdvpk5

仕事を頂けるということでしょうか?それとも、ヘルプを仕事としてお願いするということでしょうか?貴方様のIDがDQNになっているのでちょっと不安です。

ID:bdvpk5

あ、自分でやらずに第3者に仕事を振るという意味ですね!失礼しました。

ID:3w3wJn さんの回答

素朴な疑問。
jQueryじゃだめ?

ID:bdvpk5

昨日からjavascritpに触れ出したので、jQueryというものに手をつける時間がないかんじです。

ID:3w3wJn

そっか、頑張って。jsonpとかは使うの?

ID:bdvpk5

jsonpというのがよくわからないのですが、ドメインが異なるサーバー上のデータを取得する時に使うようなものなのでしょうか?www.ibm.com/developerworks/jp/web/library/wa-aj-jsonp1/
外部サイトのデータは取得する必要あります!

ID:3w3wJn

そうです。詳しくは、スラスラjsかドットインストールで。

ID:bdvpk5

ドットインストールってサイト、名前は何度か見た事ありましたけどサイト自体をちゃんと見た事無かったです。ありがとうございます!!すごいサイトですね、これは。時間のある時に気になるものをさらっとみてみたいとおもいます。

ID:K6uNkU さんの回答

トピ主は仕事でやってるのかな?

今日にはコーディング始めなきゃならないのに、基礎が分からない状態とか。無謀すぎるのではないか?何とか動くものが出来たとしても後のメンテナンスが大変そうだ。

仕事でやってるなら外注するのが最善だと思うんだが。

ID:bdvpk5

とりあえず、メンテナンスしやすくなる設計パターンを詳しく解説してくれてるページがあったので、これらを今必死に読みながらコード書いてます(汗)この業界、まだ経験があまりなくて外注する人脈というのも作ってないんですよね。。。いつも「出来ます」って言ってとりあえず仕事とってしまうんですが、今回は無謀過ぎました。。。
www.dofactory.com/javascript/design-patterns
www.addyosmani.com/resources/essentialjsdesignpatterns/book/

ID:ZUupqk

> 「出来ます」って言ってとりあえず仕事とってしまう
せめて納期を長めに設定しておくんだったねw
でもすごいよ。そうやってなんでも「できる」っていって受けてたら
できるようになるもんだ。
がんばってね!

ID:bdvpk5

ありがとうございます。納期長めに設定すると結局そこまでやらないタイプなので納期はいつも短めに設定して追い込んでます(笑)

ID:0X0MXF さんの回答

今さらだけどMVCやるならAngularとかBackbone使ったほうが楽だよ。

ID:bdvpk5

そうですね。ちょっと今回はそこに手を出す時間的余裕がないもので、ピュアJSのみでどうにか対応することにしました!

最終更新日:2014-09-02 (4,501 views)

関連するトピックス

ページ上部に戻る