jQuery-1.6.2のソースコードを見ているのですが質問させてください。
25行目の
varjQuery = function( selector, context ) {
return new jQuery.fn.init( selector, context, rootjQuery );
},
そして100行めの
jQuery.fn = jQuery.prototype = {
constructor: jQuery,
init: function( selector, context, rootjQuery ) {
の意味が分かりません。
PHP等のclassになれているとJSのクラスは戸惑うことが多いのですが、この例は最たるもので、自分の中のJSでのclassは
(1)スーパークラスのプロパティをcall()、apply()で継承
(2)スーパークラスのメソッドをprototypeオブジェクトで継承
(3)インスタンスのデータ型判定に必要なプロパティをconstructorで調整
だったのですが、スーパークラスがどの行のどれなのかも分かりません。
型やメソッド名からこれらがclassを意味しているのは分かるのですが、いったいどの部分がclass定義、継承を行っているのか教えていただけませんでしょうか?
なぜこれらがclassになっているのかが理解できません。
分るのは、jQuery.prototype.constructor = jQueryで、それをjQuery.fnに代入((3))している事です。
329行目の、jQuery.fn.init.prototype = jQuery.fn;の右辺がnew {$class}の形であれば(2)のプロトタイプチェーンの形だと分るのですが。
(1)は、init内でメンバ変数を定義したりしているので、classなのかな、という程度しか分っておりません。
jQuery.fnがコンストラクタで、jQueryがインスタンスで、var jQueryは親クラスをinitしたもの?・・・と混乱しております。
質問内容も文章が混乱していて申し訳ないです。
No.2ベストアンサー
- 回答日時:
次のように書き換えてみましょう。
//
function jQuery (selector, context) {
return new init(selector, context, rootjQuery);
}
jQuery.prototype = jQuery.fn;
//
function init (selector, context, rootjQuery) {
/* ......
this.length = 0;
...... */
}
init.prototype = jQuery.fn;
jQuery.fn.init = init;
本質的にはこういうことです(私が書くなら、こんな感じにすると思います)。したがって、new jQuery と new init は、どちらも jQuery.fn をプロトタイプとする新規オブジェクトを生成します。
---
さて、No.1 には書きませんでしたが、JavaScript のコンストラクタには 1 つの珍しい特徴があります。それは、コンストラクタがオブジェクトを return すると、new の戻り値がそのオブジェクトになってしまう、ということです。
上記の jQuery コンストラクタを見て下さい。普通、new jQuery して得られる結果は『jQuery.prototype をプロトタイプとする新規オブジェクト』だと思うでしょう。ところが、jQuery コンストラクタ内では new init の結果を return しています。だから、new jQuery の結果は、new init の結果になるのです。
var o = new jQuery; // 実は o = new init と同じ!
この o は init.prototype(= jQuery.fn)をプロトタイプとするオブジェクトですから、ちゃんと目的のものではあります。なら、jQuery.prototype をセットしているのは何のため? とお思いかもしれません。それは、instanceof の結果を調節するためです。
// o instanceof C は、o のプロトタイプが C.prototype なら true を返す
o instanceof init; // true
o instanceof jQuery; // false
これではちょっと格好悪い。そこで jQuery.prototype をセットすれば、
jQuery.prototype = init.prototype;
o instanceof jQuery; // true
はい、この通り。こんな感じで、JavaScript では instanceof の結果を後でいくらでも変更できる、というわけです。まあ、小手先の話です。
---
それと、No.1 では見落としておましたが、この書き方にはもう一つの目的があると思います。それは、new の付け忘れへの対処(あるいは new を付けなくても良いようにすること)です。
もう一度、上記の init コンストラクタを見て下さい。new init すれば、新規オブジェクトの固有プロパティとして length がセットされます。
var o = new init(...); // o.length = 0
ここで、うっかり new を付け忘れたとしたらどうなるでしょう? init() という関数呼び出しでの this はグローバルオブジェクト(ブラウザ上では Window)になり、length というグローバル変数が作られることになってしまいます。
var o = init(...); // window.length = 0
そこで、上記の jQuery コンストラクタのように書けば、new の有無に関わらず、等しく new init の結果が得られる、というわけです。
var o1 = new jQuery(...); // new init(...) の結果
var o2 = jQuery(...); // new init(...) の結果
利用者に公開するのは jQuery の方であり、init は隠し(?)メンバですから、まずはこれで十分と言えます。これも小手先と言えば小手先の話です。
Chaireさん、本当に本当にありがとうございました。
だいぶJSの事が分かったように思います。
サイ本、独習、マスター、他数冊本は読んである程度JSは理解していたつもりだったのですが(まぁ結構JSからは離れていて忘れている部分も多いでしょうが)、prototypeの部分などどの本にも載っていないような事を教えていただき非常に分かりやすかったです。
コンストラクタ内のreturn文は禁止と独習、マスター共にハッキリと書かれていましたが、そのような利用法があるとは驚きました。
Prototypoe.jsはザッと見た感じ、素直な書き方だと思いましたが、jQueryは自分には理解できない記述が多く困っておりました。
確か何かに、jQueryは芸術的な美しいコードとか書かれていたのを思い出しましたが、その分自分には難しかったです。
Chaireさんに出会えて本当に良かったと思っております。
親切丁寧にお答えいただいて、本当にありがとうございました。
No.1
- 回答日時:
クラスベース言語の「クラス」「継承」という概念をいったん捨てて下さい。
とりあえず、個人的な見解ですが:(a). プロトタイプは「デフォルト値を集約したオブジェクト」である。各オブジェクトはどのオブジェクトを「デフォルト値の集合」とするか選ぶ。
(b). デフォルト値以外が必要なときはオブジェクト固有のプロパティを生やす。オブジェクトが固有プロパティを持たなければ「デフォルト値」を探す。
JavaScript の「オブジェクト指向」とは、これだけの話です。new C(p, q) は、C.prototype を「デフォルト値集合」とし、p と q を固有プロパティの値とするオブジェクトを生成します。Object.create(O, props) は、O を「デフォルト値集合」とし、props を固有プロパティとするオブジェクトを生成します。
---
> (2)スーパークラスのメソッドをprototypeオブジェクトで継承
「デフォルト値」はメソッドに限った話ではありません。単に、メソッドは「デフォルト値」のままで十分なことが多い、というだけです。
> (1)スーパークラスのプロパティをcall()、apply()で継承
メソッドでも「デフォルト値」のままで困る場合は固有のメソッドを生やせば良い。call()、apply() を使えば他のコンストラクタから固有プロパティを輸入できますが、他のオブジェクトのプロパティ群を for...in で回して移植しても構いません。固有プロパティを生やすことが重要なわけで、何を使うかは問題ではありません。
> (3)インスタンスのデータ型判定に必要なプロパティをconstructorで調整
上書き自由な constructor でインスタンス判定することは、まずありません。この場合は単に constructor の「デフォルト値」をセットしただけです。そうすれば、new (this.constructor) のように多態的なオブジェクト複製に使われる、かもしれない。とにかく、これ自体は本質的な話ではありません。
---
前置きが長くなりました。今ダウンロードした jquery-1.6.2.js の行数で書きますが、
99 行目:
jQuery.fn = jQuery.prototype = ...
323 行目:
jQuery.fn.init.prototype = jQuery.fn;
両者から、次の関係が分かります。
jQuery.fn.init.prototype = jQuery.prototype
ゆえに、obj = new (jQuery.fn.init) によって jQuery.prototype(== jQuery.fn)をプロトタイプとするオブジェクト obj が生成されます。また、obj の固有プロパティも init() 内でセットされます。
JavaScript の instanceof 演算子は単純にプロトタイプチェーンを辿るので、jQuery.prototype を書き換えない限り、obj instanceof jQuery も true になります。表面的には「obj は jQuery クラスのインスタンス」のように見えるでしょう。しかし、それはあくまで見かけの話に過ぎません。
繰り返しますが、クラスのない JavaScript で「どれがクラスか」を考えても仕方ありません。重要なのは「どれが obj のプロトタイプか」と、「どれが obj の固有プロパティか」という 2 点だけです。
---
何でこんな書き方になっているか。想像するに、ひとつは単なるショートカット。ひとつは jQuery.fn に基本機能を集約させ、jQuery コンストラクタにぺたぺた貼付けられるプロパティから保護すること。ひとつは、jQuery の振る舞いを変更したいときに、jQuery コンストラクタそのものを書き換えるのでなく、init を切り替えるだけで済むこと。
今ぱっと思い付いたテキトーな理由ですが、それだけにしては大仰な書き方なので、他の目的もあるでしょう。
この回答への補足
Chaireさん、極めて分かりやすいご説明ありがとうございました。
JSのクラスに関して、考え方が変わりました。
ありがとうございました。
しかし、
var jQuery = function( selector, context ) {
return new jQuery.fn.init( selector, context, rootjQuery );
},
の部分の、
>new C(p, q) は、C.prototype を「デフォルト値集合」とし、p と q を固有プロパティの値とするオブジェクトを生成
により、jQuery.fn.init.prototype= jQuery.fn=jQuery.prototypeをデフォルト値集合とするオブジェクトがjQuery自身というのまだよく分かりません。
この構図だとjQuery自身が自分を・・・ってことになっているように思えるのですが、これはどういう意味なのでしょうか?
申し訳ございません。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- JavaScript jQueryで同じクラス名のものを別物として扱いたい 1 2022/06/17 14:14
- JavaScript jQueryでのドラッグアンドドロップについて 1 2022/07/30 09:10
- JavaScript jQueryでのレスポンシブが綺麗に動かない 3 2022/06/21 11:08
- JavaScript jqueryを使ったスムーススクロールのコードを書いたのですが、HTMLコード内にある、a butt 2 2022/04/14 10:59
- JavaScript jQueryローディングアニメーションのコードの以下のURL内参考サイトで提示されている 3 2023/07/03 18:29
- JavaScript jQueryでのドラッグアンドドロップについて 1 2022/07/07 21:04
- JavaScript プラグイン無しでContactform7にdatepickerを実装 3 2022/10/25 02:18
- AJAX JavascriptからPHPへのAjax通信でnullが返ってくる 3 2022/08/03 22:00
- PHP アップロードファイルの数に応じてCSSを動的に変更したいのですが、方法がわかりません 3 2023/07/23 21:59
- JavaScript 階層別の組織図の自動作成について 1 2022/10/26 13:42
関連するカテゴリからQ&Aを探す
おすすめ情報
- ・「みんな教えて! 選手権!!」開催のお知らせ
- ・漫画をレンタルでお得に読める!
- ・【選手権お題その1】これってもしかして自分だけかもしれないな…と思うあるあるを教えてください
- ・【穴埋めお題】恐竜の新説
- ・我がまちの「給食」自慢を聞かせてっ!
- ・冬の健康法を教えて!
- ・一番好きな「クリスマスソング」は?
- ・集合写真、どこに映る?
- ・自分の通っていた小学校のあるある
- ・フォントについて教えてください!
- ・【大喜利】【投稿~12/6】 西暦2100年、小学生のなりたい職業ランキング
- ・これが怖いの自分だけ?というものありますか?
- ・スマホに会話を聞かれているな!?と思ったことありますか?
- ・それもChatGPT!?と驚いた使用方法を教えてください
- ・見学に行くとしたら【天国】と【地獄】どっち?
- ・とっておきの「夜食」教えて下さい
- ・これまでで一番「情けなかったとき」はいつですか?
- ・遅刻の「言い訳」選手権
- ・「覚え間違い」を教えてください!
- ・とっておきの手土産を教えて
- ・「平成」を感じるもの
- ・この人頭いいなと思ったエピソード
- ・あなたの「必」の書き順を教えてください
- ・10代と話して驚いたこと
- ・14歳の自分に衝撃の事実を告げてください
- ・人生最悪の忘れ物
- ・あなたの習慣について教えてください!!
- ・都道府県穴埋めゲーム
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
Excelで =EMBED("Acrobat Docu...
-
パワーポイントのVBAでテキスト...
-
EXCEL VBAにて動的にCheckBOXを...
-
時間帯判定をする。
-
Vbで通常使用するプリンターを...
-
ワイルドカード<?>と型パラメー...
-
ASP.net 教えてください!!(...
-
開始日(Date型)から終了日(Date...
-
VBAのWindowオブジェクトとWork...
-
Listに格納されているオブジェ...
-
オブジェクトに値を保持させる...
-
戻り値がクラスオブジェクト
-
VBA 同じ名前のオブジェクトを...
-
オブジェクトと関数の違い
-
VBAからノーツを起動
-
withを入れ子にして使う方法
-
.getElementById()のエラーにつ...
-
LISTBOXの内容が更新されま...
-
0byteのallocaやmemset
-
jQuery.cloneのsubmitについて
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
パワーポイントのVBAでテキスト...
-
C#でフォームのオブジェクト名...
-
Excelで =EMBED("Acrobat Docu...
-
VBA 同じ名前のオブジェクトを...
-
EXCEL VBAにて動的にCheckBOXを...
-
Object型からDouble型へのキャスト
-
VBAのWindowオブジェクトとWork...
-
ワイルドカード<?>と型パラメー...
-
ビジュアルC++でボタンの有...
-
COMコンポーネントって何?
-
ASP.net 教えてください!!(...
-
Accessの連結・非連結オブジェ...
-
LISTBOXの内容が更新されま...
-
オブジェクトレベルとメタレベル
-
error C2712: オブジェクト ア...
-
時間帯判定をする。
-
newは明示的にした方が良いのか?
-
CoCreateInstanceでエラーになる。
-
ワードで画像をドロップすると...
-
0 == False はいいけど
おすすめ情報