search phpbb-phpbb-FC2BLOG-Info-Edit Template-Post-Edit-Upload-LogOut
jQuery解読作業を進めるにつれ、Javascriptの基礎が如何に分かっていないか、ほぼ毎日のように痛感させられます。その意味ではjQuery解読は無謀なチャレンジであった訳ですが、それでも誤謬を犯すマイナスを埋め合わせて遙かに余りあるプラスがあることも毎日自覚されるので、恥を忍んで引き続きjQuery解読を進めるつもりでいます。
しかし、基礎の基礎が余りに分かってない自分に嫌気が指してきてしまい、匙を投げ出すような醜態は演じたくありません。そこで、自戒を込めて敢えて誤解していたこと、理解していなかったこと、不十分な理解に留まっていたことなどについて、つらつらと記述していきたい、と思います。
ここでは return 値の受け取り先について、『Javascript第5版 日本語訳』における記述の曖昧さを指摘すると共に、jQuery().init()メソッドにおけるreturnチェーンについてまとめたいと思います。
四則計算のような簡単な関数の場合、return で返される値は余りに明白です。return a*b ならば a に b を乗じた計算結果が返値になります。
またreturn Boolean の場合には true か false が返されます。そして同時に或る関数から true や false が返された場合のJavascriptの振る舞いについても、状況に応じた一定の決まり事があるようです。(status行に関するコードやタグ属性として記述されたJavascript文の場合等)
一般に、返値は数値、文字列、論理値及びオブジェクトのいずれでもあり得ます。クロージャーの場合のように関数自身を返値とすることさえある訳ですから、返値はあっさり言えばJavascriptで扱えるものならば「何でもあり」と思います。
『Javascript第5版』には「return はそれを含む「関数の呼び出し元に返値を返す」」と書いてあります。
関数がリテラル標記されている場合で右辺の関数が無名だった場合について考えてみます。
jQuery関数もこのように無名関数として定義されていますが、例えば、var funcName = function (a,b) {return a + b }; のような場合です。
この関数は funcName(2,3) のような標記によって呼び出され returnすべき値として 5 を算出します。この場合の呼出し元は言うまでもなく funcName(2,3) です。
つまり、変数 funcName に返値 5 が代入されるのではなく、 funcName は関数オブジェクトそのものであって、alert( funcName ) の出力結果は function (a,b) {return a + b } となります。
確かに var result = funcName (2,3) とすれば変数 result に 返値 5 が代入されますが、それは呼出し元に返された return 値が変数に代入されているに過ぎません。返値を受け取る受け取り先は変数result でも、funcName関数オブジェクトでもありません。
以上は余りに当たり前のことですが後述することとの関係でまず確認のために記しました。
よく知られているように、無名関数をあるオブジェクトのプロパティ値に設定する場合、つまり或るオブジェクトのメソッドにするには obj.meth = function (a,b) {return a + b }; とします。
この場合オブジェクト obj のプロパティである meth に関数オブジェクトへの参照が代入され、実行演算子()を使って obj.meth(3,4) のように指示してこの関数が実行されます。
では、この場合の返り先はどこでしょうか? オブジェクトobjでしょうか?
もちろんそれは違います。リテラル標記時の左辺が返り先でなかったのと全く同様に、この場合にも返値の受け取り先は obj.meth(3,4) です。
さて、ここから本題です。『Javascript第5版』では次のような一説があります。
オブジェクトを介して呼び出す関数のことをメソッドと呼びます。メソッドを呼び出したオブジェクトは暗黙的に引数として関数に渡されます。(p.123)
この文章を読むと、メソッドの場合の呼出し元は当該オブジェクトであり、他所で「関数の呼び出し元に返値を返す」と書いてあるのだから、メソッドの返値はそれを呼び出したオブジェクトに受け取られる、と理解してもおかしくありません。
しかし、オブジェクトはメソッドの呼び出し元ではありませんし、返値はオブジェクトに返される訳ではありません。オブジェクトを介して、オブジェクト上で、当該関数が実行されるだけです。
「オブジェクトを介して呼び出す」との表現と「メソッドを呼び出したオブジェクト」という表現は微妙に意味が異なります。介して呼び出された場合の呼出し元は、決して介されたオブジェクトではないのです。従ってメソッドを呼び出したオブジェクトという表現は適切さを欠くと言わざるを得ないでしょう。
この曖昧な表現故に、少なくとも私は、メソッドの場合には当該オブジェクトに返値が返される、と誤解させられたのですから。
「メソッドを呼び出したオブジェクト」は原典では「When a function is invoked on an object, the function is called a method, and the object on which it is invoked is passed as an implicit argument of the function.」(アンダーライン部が「メソッドを呼び出したオブジェクト」と訳された箇所)です。アンダーライン部を直訳すれば「それ(メソッド)がその(オブジェクト)上で呼び出されたオブジェクト」はとなり「メソッドを実行したオブジェクト」と表現した方が、「呼出し元」なる表現との差異を明確にするためにも適切ではないか、と思います。
呼出し元が或るオブジェクト上(あるいは「内」)の1つのプロパティである、メソッド関数を実行し、その結果が呼出し元に返されるのですから。
一方「return文が指定されていれば、関数の実行はここで中断され、式の値(もしあれば)が呼び出され呼出し元へ返されます(p.124)」は原典では「it causes the function to stop executing and to return the value of its expression (if any) to the caller.」です。callerは訳すと確かに「呼出し元」となります。
つまり call と invoke をそれぞれ異なる適切な言葉で表現すべきであって、共に「呼び出す」と訳していることが読者に混乱を招いている、と思います。
<1> 55: this[0] = tmp; 56: this.length = 1; 57: return this; <2> 65: return new jQuery( context ).find( selector ); <3> 72: return this.setArray([ selector ] );
init() メソッド内には this を直接返す場合(<1>)、新たなインスタンスを返す場合(<2>)、this.setArray() メソッドを返す場合(<3>)など様々な return 値があり大変勉強になります。
下記コードの進行過程を具に解析する作業を通じて返値を解析してみます。
var jQuery = function (a,c){
return this instanceof jQuery ? this.init(a,c) : new jQuery(a,c)
}
因みに、jQuery()は var jQuery = function(){・・・return this.init()} というリテラル形式関数ですから、先に見たように無名関数から返された return 値はこの式内では受け取れません。受け取り先はこの関数を呼び出したもの、つまりユーザーが入力した jQuery(x,y) に他なりません。
また蛇足ながら、returnチェーンこそがメソッドチェーンを実現している「 秘策 」に他なりません。
55行:this[0]にtmpが代入されます。つまりインスタンスの最初の要素がtmpとなります。
56行:次にその配列の要素数が1とされます。これによりもし要素数が2以上であった場合であっても強制的に1となります。
57行:最後にこうして加工された this、つまりインスタンスが jQuery()関数に 返され、最終的にユーザー入力 API に返されます。
実は、jQueryではインスタンスがjQuery()関数に返されるシーンは結構沢山あります。それこそがjQuery.jsの神髄とも言えるメソッドチェーンを実現するために、こうした仕様となっているのでしょう。
これは細かく説明するまでもなく、new 実行後の新たなインスタンスがjQuery()関数に返され、それがユーザー入力 API に返されることになります。
この場合には setArray() メソッドを分析すれば、Array.prototype.push.apply( this, a ) によって、取得されたエレメントノードを要素とする配列がインスタンスオブジェクトに返され、それが init() からの返値となり、結局それがユーザー入力 API に返されることになります。
以上のように、this キーワードと return が組み合わされて使用されると、一見複雑に見えます。jQueryでは生成されるインスタンスを明示的に固有の変数に代入しませんので、インスタンスオブジェクトが直接変数としてコード内に出現することはありません。、それは常に this によって指し示されるだけであり、このことがコードの理解をより一層分かりにくくしているのではないか、と痛感しています。この見えないインスタンスに散々苦労させられたのは、私自身に他なりませんから(苦笑)。
変数に代入されない return 値は一体どこに記憶されるのでしょう?
もちろん物理的にはメモリ上ですが、Javascriptにおいてどこに保存されるのでしょうか?
裏返せば変数に代入されない返値を参照する何らかの方法はあるのでしょうか?
関数が定義されるとCallオブジェクトが生成され、そのプロパティに引数やローカル変数に格納されるそうですので、このオブジェクトの中に返値も保存され、変数が代入先として用意されていれば、Callオブジェクトのプロパティとして記憶された返値が、当該変数に代入されるのでしょうか?
このCallオブジェクトのプロパティに返値が保存される、という考えは全くの推測に過ぎませんが、他に考えようがありません。
次のようにして全く変数に代入されない返値 98 を取得することが可能です。
var ret= (function() {return arguments[0] + arguments[1]; })(20,78)
また決して好ましい方法とは思いませんが、徒に複雑にしただけの以下のようなクロージャーを使っても同様に返値を取得することが出来ます。
(function () {
var r=arguments;
return function() {return r[0]+r[1]; };
})(20,78)() //これを実行すると 20 + 78 のreturn値である 98 が取得できる。
上のコードでは、まず無名関数 function () の引数に 20と78を代入して無名関数を実行し【(20,78)】、更にその返値として返される関数を実行【最後の()】して計算させ返値を求めています。
90%近いシェアを握っているインターネットエクスプローラの描画エンジンを利用したタブbrowser。沢山のタブbrowserがあるが、多機能、カスタマイズフリー、スクリプト利用等で一日の長がある。Gekkoエンジンへの対応も行われ、IEからの自立独立の方向に向かっている。2005年7月にはIE7が登場する見通しの中で、今後の発展が望まれる。
多様なCSS作成支援機能を備えた、タグ入力式 HTML&CSS作成支援エディタ。スキンデザインもすっきりしている。テキストエディター上で作成するよりも確実で安全にタグ打ちが出来る。
文字コードを選べないのが欠点。
StyleNote同様のタグ入力式 HTML&CSS 作成支援エディタ。長年使用してきたが現在StyleNoteに乗り換えつつある。
クリップボード履歴情報を活用する為のソフト。画像まで履歴を取ってくれるのが嬉しい。このソフトを使わない日は絶対ない程に重宝し、愛用している。
起動中のウィンドウの「コピーできない」説明文などの文字列を取得し、コピー可能な文字データにするツール。何かと便利。
ストリーミングデータを保存することが出来るソフト。動画利用には不可欠なソフトだ。
無料ながらレイヤー機能を有し、スクリプトによる拡張も可能な、sleipnir作者が提供している優れもの画像編集ソフト。
画面キャプチャソフトと言えばこれに勝るものなし、ではないだろうか? 様々な取得方法を有しており、ブログ作成にもHomepage作成に不可欠だ。Jtrimと並んでWoodyBellsの作品。
複数ファイルの同時編集は出来ないが、透過pngも作れる画像編集ソフト。
(以下当該サイトから抜粋)初心者にも簡単に操作が出来るフォトレタッチソフトです。多くの加工機能で画像に様々な効果を与えることができます。非常に軽快に動作するため、ストレスなく操作できます。
Animation Gifファイルを作れる無料ソフト。
キャプチャソフト。画面内にサイト全体が表示しきれない場合でも、これを使えば全体をキャプチャすることが出来る。
画像処理。画像のフォーマット変換のみならず、色数やサイズ、圧縮率の変更まで一括処理できてしまう『BatchGOO!』は、大量の画像をまとめて処理したいときに大変便利なソフト。BMP, TIFF, JPEG, PCX, PNG の相互変換をはじめ、色数・サイズ・解像度の統一、JPEG圧縮率の調節など、ホームページ用の画像や携帯電話用の壁紙を揃えるのに抜群の相性を見せる。(Vectorの当該ソフト紹介頁より抜粋引用)
名前から直ぐに想像が付くように画像のサイズを測るためのソフトだ。Homepage作成には欠かせない。2カラム、3カラムのレイアウトを行う場合に大変重宝する。
ランチャーソフトは沢山あるが、中でもこれが一押しだ。2年以上使ってきたがその操作性には毎日満足している。これを使い始めてからデスクトップには一切のアイコンを表示することをやめてしまった。
AdobeReader7によって、起動時間が長すぎるという長年のユーザーの不満はある程度解消した。そのためこの高速化ソフトは存在価値が低下してしまったかもしれない。AdobeReader6迄はこのソフトによる起動高速化で恩恵を受けてきた。
IE専用が難点だが、様々なサイト内でIDやパスワードを入力するのに重宝するソフト。コンテキストメニューから簡単に起動できるのがGood! sleipnir等のIEの描画エンジンを利用しているブラウザでも使える。
利用しているパソコンの諸元値を取得するには、このソフトがベストだ。インストール済みソフトの一覧が取得できるのも嬉しい。
WMPは機能が豊富なだけ重い。RealPlayerも同様だ。そこでMedia Player Classicを使いたい。動作が軽快なだけではなく、対応しているファイル形式もすこぶる多く、これひとつで、wmvもrmも表示できてしまうのだから凄い! 数多あるMedia Playerの王様と言えるだろう。
自宅でPCを起動しているときには必ず起動しているメディアプレーヤー。何かと過剰なWinampよりも、起動も速くスキンはシンプルだ。
DivX, Xvid, Mov, Vob, Mpeg, Mpeg4, avi, wmv, dv, などの動画をDVD-Video形式に変換できるフリーソフト。クリックするとDVD関連ソフト紹介サイト=「DVDなToolたち」なるHomepageが開きます。