(function(global, noValue) {
global.myLib = function() {
console.log('myLib関数が実行されました');
};
})(window);
疑問点提起:1.自己呼び出し関数は外部のグローバル変数にアクセスできるのに、なぜwindowを引数として渡す必要があるのか?2.undefinedを引数として渡す意味は何か?
個人的な理解1:まず、実引数としてwindowを渡すことで、仮引数のglobalが外部のグローバル変数windowを指すことを明示しています。では、なぜ直接外部のwindowにアクセスせず、ローカル変数としてアクセスするのでしょうか?二つの利点があります。1.windowを毎回使用するたびに外部のグローバルwindowを探す必要がありますが、その検索プロセスはローカル変数にアクセスするよりも遅いです。2.ローカル変数を使用することは圧縮に有利で、仮引数のglobalを短い文字(例えばg)に書き換えることができ、ファイルサイズが小さくなります。
個人的な理解2:undefinedをなぜ仮引数として使用するのか(実際には実引数が渡されない場合はundefinedになります)。理由はIE678において、undefinedはキーワードではなく変数として変更できるためです。
// 厳格モードは不要です
var // メインのルートjQuery(document)への参照
mainJQuery,
// DOM準備完了時に使用されるDeferred
readyQueue,
// IE9サポート
// `typeof xmlNode.method` の代わりに `xmlNode.method !== undefined` を使用するため
core_undefinedType = typeof undefined,
// window引数に応じて適切なdocumentを使用(サンドボックス環境)
currentLocation = window.location, // アドレス情報
currentDocument = window.document, // documentオブジェクト
htmlElement = currentDocument.documentElement, // htmlオブジェクト
// jQueryが上書きされた場合のマッピング
originalJQuery = window.jQuery, // 外部のJQueryをoriginalJQueryに代入、競合を防ぐ
// $が上書きされた場合のマッピング
originalDollar = window.$, // 外部の$をoriginalDollarに代入、競合を防ぐ
// [[Class]] -> タイプペア
typeMap = {}, // $.type()で使用される型判定用オブジェクト
// 削除されたデータキャッシュIDのリスト、再利用可能
deletedCacheIds = [], // データキャッシュに関連、2.0.3ではオブジェクト指向方式を採用
libVersion = '2.0.3',
// 一部のコアメソッドへの参照を保存
arrayConcat = deletedCacheIds.concat,
arrayPush = deletedCacheIds.push,
arraySlice = deletedCacheIds.slice,
arrayIndexOf = deletedCacheIds.indexOf,
objectToString = typeMap.toString,
objectHasOwn = typeMap.hasOwnProperty,
stringTrim = libVersion.trim
ソースコードでは、まずvarで変数を宣言してから後で値を代入する方法を使用しています。この方法には**圧縮に有利(式として書くと圧縮できないため)**という利点があります。変数は一文字で表現できます。もう一つの利点は、変数が何を意味するかが分かりやすく、メンテナンスが容易になることです。例えば、a+10(10が何を意味するか不明)と var length = 10; a+ length の違いです。
次に、core_undefinedType = typeof undefinedについて説明します。typeof undefinedの値は"undefined"なので、core_undefinedType = "undefined"となります。もしcore_undefinedTypeが"undefined"であれば、その変数は未定義です。window.a == undefinedでもチェックできますが、XmlNode.methodではサポートされていません。これは特殊なケースで、HTML環境では問題ありませんが、完全性のためにtypeof undefinedを使用しています。
なぜ直接core_undefinedType = "undefined"と書かないのか?これは圧縮に不利だからです。
myFramework = function(selector, context) {
// 実際にはinitコンストラクタを拡張したものがjQueryオブジェクト
return new myFramework.fn.init(selector, context, mainJQuery);
}
この部分では何が行われているのでしょうか? myFramework().css(), myFramework().width()などのメソッドにはすべてmyFramework()があります。myFramework()はmyFramework.fn.initのインスタンスを返しており、これはmyFramework.fn.initのプロトタイプにメソッドがあることを示しています。272行目にあるmyFramework.fn.init.prototype = myFramework.fn;により、myFrameworkのプロトタイプの参照がinitのプロトタイプに割り当てられています。これは参照型の代入であり、myFrameworkのプロトタイプが変更されると、initのプロトタイプもそれに伴って変更されます!【css(), width()などのメソッドはすべてmyFrameworkのプロトタイプで定義され、その後initのプロトタイプに参照されています】疑問点:なぜメソッドをjQueryプロトタイプ上に書くのか?なぜjQueryプロトタイプのメソッドをinitのプロトタイプで置き換えるのか?なぜinitはjQueryのプロトタイプ内に存在するのか?