私はしばらく jQuery を使ってきましたが、実際には理解できない API 実装がいくつかあります。編集者は関連するソースコードを参照し、私の学習プロセスと成果を全員と共有するようになりました。
以下では、jQuery の実装アイデアを中心に、簡略化したコードを使用して紹介します~>_
//匿名立即执行函数 //.防止污染全局空间 //.选择性保护内部变量 (function(window, undefined){ //第二参数undefined设置而不传的原因: // 外部发生这种情况:var undefined = 时,undefined会被篡改 // 设置第二参数而不传,则undefined就会被重置回原来值 function jQuery(sel){ return new jQuery.prototype.init(sel); } jQuery.prototype = { constructor: jQuery, init: function(sel){ if(typeof sel === 'string'){ var that = this; //jQuery内部使用的是Sizzle,这里使用querySelectorAll替代 var nodeList = document.querySelectorAll(sel); Array.prototype.forEach.call(nodeList, function(val, i){ that[i] = val; }) this.selector = sel; this.length = nodeList.length; } } } jQuery.prototype.init.prototype = jQuery.prototype; //对外暴露jQuery:将jQuery绑定在window上面 window.$ = jQuery; })(window);
--------------------------
jQuery は最初に匿名の即時実行関数で内部をラップし、5 行目で外部に公開します。
$("div") を外部から呼び出すと、実際には内部の jQuery("div");
(function(window, undefined){ //内部变量 //对外暴露jQuery:将jQuery绑定在window上面 window.$ = jQuery; })(window); $("div")
さて、もう少し複雑にしましょう。次のコードは主に、図に示すように相互参照を実装します。
コードの 2 行目からわかるように、jQuery は jQuery.prototype.init を使用して jQuery オブジェクトをインスタンス化しますが、これにより問題が発生します。
インスタンス化されたオブジェクトは init の変数にのみアクセスできますが、jQuery.prototype にはアクセスできません (jQuery によって提供される API はこのオブジェクトにバインドされています)。
それでは、コードの 21 行目を記述して、init.prototype を jQuery.prototype にポイントするだけです。
これで完了です。init を使用してインスタンス化すると、init スコープで jQuery.prototype にアクセスできるようになります。
function jQuery(sel){ return new jQuery.prototype.init(sel); } jQuery.prototype = { constructor: jQuery, init: function(sel){ if(typeof sel === 'string'){ var that = this; //jQuery内部使用的是Sizzle,这里使用querySelectorAll替代 var nodeList = document.querySelectorAll(sel); Array.prototype.forEach.call(nodeList, function(val, i){ that[i] = val; }) this.selector = sel; this.length = nodeList.length; } } } jQuery.prototype.init.prototype = jQuery.prototype;
オブジェクト間の参照を実際に jQuery-->jQuery.prototype に単純化できるように、jQuery 関数を使用してオブジェクトをインスタンス化すると仮定します。
しかし、呼び出しは new $('div') のように複雑になるため、この考慮事項に基づいて (推測 (⊙0⊙))、より複雑な実装が内部で使用されて呼び出しが簡素化されます。
--------------------------
さて、最後に init の実装を見てみましょう。コードも簡略化され、最も一般的に使用されるケースのみが実装されています。
jQuery は、取得した nodeList を配列に処理し (その後の使用のために)、その配下に長さやセレクターなどの変数をマウントします。
init: function(sel){ if(typeof sel === 'string'){ var that = this; //jQuery内部使用的是Sizzle,这里使用querySelectorAll替代 var nodeList = document.querySelectorAll(sel); Array.prototype.forEach.call(nodeList, function(val, i){ that[i] = val; }) this.selector = sel; this.length = nodeList.length; } }