Kanasan主催のJavascript勉強会であるところのKanasan.jsに行ってきました。
私はJavascriptはあまり書かないのですが、この機会にちょっくら勉強するか、というつもりで参加しました。Prototype.jsのCodeReadingだったのですが、どっこい、これがなかなかおもしろくて、Javascriptのキモイ側面がいろいろと垣間みれて興味深かったです。キモイ言語サイコー。
参加者のyharaさんがすでにまとめを書かれているので、内容はそちらを参照してください。yhara++。
yharaさんが書かれた以外の箇所で個人的に気になった部分のメモをyharaスタイルで以下にまとめておきます。prototype.js 1.5.1.1ですよ。
l.12
Browser: { IE: !!(window.attachEvent && !window.opera), Opera: !!window.opera, WebKit: navigator.userAgent.indexOf('AppleWebKit/') > -1, Gecko: navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('KHTML') == -1 },
ここの!!はObjectをBooleanに変換するのに使われているらしい。例えば、window.operaに何かしらのオブジェクトが入っていると、一度目の!でfalseになって二度目の!でtrueになるとか。
l.44
Object.extend = function(destination, source) { for (var property in source) { destination[property] = source[property]; } return destination; }
extendというと一瞬Javaのextendを想定してしまうけど、この実装だと、prototypeチェーンされるわけではないので、どっちかというとmixinという感じなのね。ほかのライブラリはちゃんと継承させるための関数が用意されていたりするのかな。
l.102
Function.prototype.bind = function() { var __method = this, args = $A(arguments), object = args.shift(); return function() { return __method.apply(object, args.concat($A(arguments))); } }
yharaさんも書かれていたけど、ちょっとだけ。一個目のargumentsと二個目のargumentsが別のものを指していることにはじめ気づかなくてはまった。
l.281
unescapeHTML: function() { var div = document.createElement('div'); div.innerHTML = this.stripTags(); return div.childNodes[0] ? (div.childNodes.length > 1 ? $A(div.childNodes).inject('', function(memo, node) { return memo+node.nodeValue }) : div.childNodes[0].nodeValue) : ''; },
ここの最後の三項演算子はわかりにくいなー。はじめの真偽値評価を逆にしたほうがきれいにかけないかな。
return !div.childNodes[0] ? '' : div.childNodes.length > 1 ? $A(div.childNodes).inject('', function(memo, node) { return memo+node.nodeValue ) : div.childNodes[0].nodeValue ;
結局ステートメントの長さが流すぎでいまいちの見た目になっちった。*1
若干yharaさんの記事の劣化コピーになった部分もありますが、あしからず。
Javascriptにくわしい人もたくさん参加されていて、わからないときには聞けば答えていただけたり、時にはみんな議論したりでかなり楽しかったです。あと、時折現れる言語の濃い話も格別。ぜひ、またやりたいですね。あと、カレーがおいしかったです。
最後になっちゃいましたが、短い期間でいろいろと準備されたkanasan、裏からいろいろと手を引いていた黒幕の@ujihisaさんどうもありがとうございましたー。
*1:表示のインデントがいまいちおかしいのはなんで?