Prototype 1.6.0 RC
でましたね。Prototype 1.6.0 release candidate
WEB界隈から離れてしばらくたちますが、またいつWEB界隈に戻るかわからないので一応追ってます。
1.6ではついにClass周りに手が入りました。Prototype.jsといえばシンプルすぎるClass周りとプロパティをコピーするというなんちゃって継承がウリ(?)だったわけですが、1.6からは違います。もうオレオレクラス定義ライブラリをわざわざ使わなくても大丈夫。
公式にも例がありますが、こんな感じでちゃんと継承できるようになりました。
- var Animal = Class.create({
- initialize: function(name) {
- this.name = name;
- },
- eat: function() {
- return this.say("Yum!");
- },
- say: function(message) {
- return this.name + ": " + message;
- }
- });
- var Eatable = {
- eaten : function() {
- return this.say("help me!!!");
- }
- }
- var Mouse = Class.create(Animal, {
- });
- //syntax sugar for Object.extend
- Class.mixin(Mouse.prototype, Eatable);
- // subclass that augments a method
- var Cat = Class.create(Animal, {
- eat: function($super, food) {
- if (food instanceof Mouse) return [food.eaten(),$super()].join("\n");
- else return this.say("Yuk! I only eat mice.");
- }
- });
- var a = new Cat("Tama");
- alert(a.eat(new Mouse("Nezumy mouse")));
単にプロトタイプチェーンをつなげるだけではなくて、オーバライドされたメソッドの引数名を取得して(toStringしてgrepですね)、$superだった場合、自動的に親クラスのメソッドを$superとして渡してくれます。地味に便利。
あとはsyntax sugarとしてClass.mixinがあります。まぁObject.extendなんですが、こっちの方がわかりやすいですよね。
そのほかもいっぱい機能が追加れさてれてますね。個人的にはdocument.observe("contentloaded", function() { ... })て感じでサポートされたDOM完了時点でのイベントと、
- $("container").observe("titleChanged", function(event) {
- this.highlight({ duration: 0.5 });
- });
- $("title").fire("titleChanged");
って感じのカスタムイベントが必ず使いそうな機能かな。
資格の勉強とかもそろそろしなきゃなー、と思いつつ、Scalaでパーサコンビネータライブラリがついたので、Schemeの処理系でも実装したいなあ、と思い始めてる今日この頃。
$$で属性セレクタ
これはかなり嬉しい機能だなあ。 最近Prototype.jsの$$で属性セレクタが使用できるようになりました。
どんな風にかけるのか、コードをテストから引っ張ってきてみました。
- $$('a[href="http://inforno.net/#"]')
- $$('a[class~=internal]')
- $$('*[xml:lang|="es"]')
- $$('*[xml:lang|="ES"]')
- $$('a[href!=#]')
- $$('div[style] p[id] strong')
- $$('a[class~=external][href="http://inforno.net/#"]')
こんな感じです。 値はクオートしてもしなくても大丈夫っぽいですね。
すばらすい。inputに対する操作なんかで特に便利。今までちょっとボタン操作するためだけに、そのボタンにIDふったりクラスふったりしてたんですけど$$('#hoge input[type=submit]')でいけるんだなあ。そんなにパフォーマンスに気をつかわなくて良いページでは使ってみよう。
Element.extendの動向。
最近prototype.jsではSelectorとDOMがよく動きます。 仕事でも使っているし、重要な部分なのでここのところウォッチしています。
最近、実は書こうと思ってたElement.extendの問題が解決されました。 問題:Incredible memory leak in IE
これは見る人が見ればパッと見で「これはヤバいんじゃね?」と思ったんじゃないでしょうか。 わからなかった人は上記のURLにも載っている http://msdn.microsoft.com/library/default.asp?url=/library/en-us/ietechcol/dnwebgen/ie_leak_patterns.asp を見ておくと今後悩むことが減るかもしれません。
リンク先をみたらなにが問題かわかるのであえては書きません。
もう一個、興味深いのはElement.extend cripples $() performanceでの議論です。 前に書いた記事と似た主張や議論がなされています。うちの会社にも英語苦手な人がいるので簡単に要旨を。
- Element.extendはパフォーマンスに問題がある。前のままにしてほしい。
- http://dev.rubyonrails.org/changeset/4094でだいぶマシになっているよ? 解説:以前はそれぞれのElementについてElement.Methodsのメソッドにelementをbindしてコピーしていた。 つまりElementの数に比例してメモリを使用する。しかし4094でキャッシュを導入したので一定数のメソッドしか生成しない。
- とりあえずElement.extendのパフォーマンスをあげることにフォーカスしよう。
- Element.extend = Prototype.Kってかけばとりあえず大丈夫じゃね?
- でもscriptaculousが完全にextendされてる前提でコードかいてるから動かなくなるじゃん。 解説:scriptaculousは3月28日にprototype.js 1.5_pre1をバンドルしてバージョン1.6をリリースした。 このバージョンではelement.setStyle({top: ''})とかelement.show();みたいにガンガンElement.extendを活用している。
- まぁとりあえずElement.extendが必要ないときはPrototype.Kにしとけばいい。
- FirefoxやSafariは高速化できる(前のエントリーとほぼ同じ)。しかしprototype.jsに組み込むとscriptaculousのElement.Methods拡張が反映されない。
というわけでElement.extendはこれでちょっと落ち着いた感じ。個人的にはElement.extend無効化して使っていきたいなーって思ってたりしてたんですけどscriptaculousがやっぱりガンガン使ってきたので、まぁ様子見てみます。