Возвращаемый массив jQuery селектора
Здравствуйте всем!
Пытаюсь написать свой фрэймворк для опыта. Образец jQuery. Застрял на моменте когда селектор jQuery возвращает массив с dom елементом и так же сам jQuery объект. Начал отслеживать историю развития фрэймворка, оказалось что только в версии http://code.jquery.com/jquery-1.4.1-vsdoc.js они реализовали эту фичу. Честно говоря не смог разобраться как это они реализовали. Заранее спасибо! |
function jQuery() { return new jQuery.prototype.init( arguments ); } jQuery.prototype = { constructor: jQuery, init: function( selector, context ) { this[0] = "lala"; this[1] = "tratata"; this.length = 2; return this; }, length: 0 } jQuery.prototype.init.prototype = jQuery.prototype; alert( JSON.stringify( jQuery() ) ); |
devote, вы возможно не поняли вопроса. Этот момент я уже реализовал для себя, у меня так же возвращается объект. А вы попробуйте выполнить $('#someID') в консоле ФФ, то увидите что в результате появится не объект, а массив с dom элементом [div#someID]. Я дебажил и выводил ссылку на объект this до ретурна, она уже в тот момент ссылалась на пустой массив.
|
хотя правильнее показать на таком примере:
function jQuery( selector, context ) { return new jQuery.prototype.init( selector, context ); } jQuery.prototype = { constructor: jQuery, init: function( selector, context ) { context = context || document; return jQuery.makeArray( this, context.querySelectorAll( selector ) ); }, length: 0 } jQuery.makeArray = function( array, obj ) { var length = obj.length; for( var i = 0; i < length; i++ ) { array[ i ] = obj[ i ]; } array.length = length; return array; } jQuery.prototype.init.prototype = jQuery.prototype; var s = "", jq = jQuery('*'); for( var k in jq ) { s += k + ": " + jq[k] + "\n"; } alert( s ); |
Да с этим момент, я тоже разобрался. А вы можете ответить на счет этого момента
function jQuery( selector, context ) { return new jQuery.prototype.init( selector, context ); } jQuery.prototype = { constructor: jQuery, init: function( selector, context ) { if ( !selector ) { console.log(this); // [] как??? return this; } context = context || document; return jQuery.makeArray( this, context.querySelectorAll( selector ) ); }, length: 0 } jQuery.makeArray = function( array, obj ) { var length = obj.length; for( var i = 0; i < length; i++ ) { array[ i ] = obj[ i ]; } array.length = length; return array; } jQuery.prototype.init.prototype = jQuery.prototype; |
Цитата:
Вот вам мини jQuery, и джуквери сделан именно по такому принципу. <div>Первый дивак</div> <div>Второй дивак</div> <script> (function( window, undefined ) { function jQuery( selector, context ) { return new jQuery.prototype.init( selector, context ); } jQuery.prototype = { constructor: jQuery, init: function( selector, context ) { context = context || document; return jQuery.makeArray( this, context.querySelectorAll( selector ) ); }, length: 0 } jQuery.prototype.init.prototype = jQuery.prototype; jQuery.makeArray = function( array, obj ) { var length = obj.length; for( var i = 0; i < length; i++ ) { array[ i ] = obj[ i ]; } array.length = length; return array; } jQuery.each = jQuery.prototype.each = function( object, callback ) { if ( typeof object == 'function' ) { callback = object; object = this; } if ( object.length === undefined ) { for( var i in object ) { if ( callback.call( object[ i ], i, object[ i ] ) === false ) { break; } } } else { for( var i = 0, j = ~~object.length; i < j; i++ ) { if ( callback.call( object[ i ], i, object[ i ] ) === false ) { break; } } } return this; } window.jQuery = jQuery; })( window ); jQuery( "div:first-child" ).each(function() { this.style.cssText = "width: 100px; height: 100px; background-color: #f00;"; }); </script> |
console.log(this); // [] как???
в какой это версии ? в том примере кода который вы привили такое попросту невозможно |
Цитата:
А это был не мой пример, я только добавил часть кода которая есть в jQuery в код предложенные devote, что бы показать как написанно в jQuery. этот пример с версии 1.7.2 jQuery.fn = jQuery.prototype = { constructor: jQuery, init: function( selector, context, rootjQuery ) { var match, elem, ret, doc; // Handle $(""), $(null), or $(undefined) if ( !selector ) { // тут я решил проверить this. Можете сами протестить результа будет равен пустому массиву. return this; } // Handle $(DOMElement) if ( selector.nodeType ) { this.context = this[0] = selector; this.length = 1; return this; } // The body element only exists once, optimize finding it if ( selector === "body" && !context && document.body ) { this.context = document; this[0] = document.body; this.selector = selector; this.length = 1; return this; } Т.е. говоря иначе. Если в консоле ФФ набрать $('#someID') то до версии 1.4.1 результат был jQuery{.....} а с версии 1.4.1 и выше результат [tag#someID] |
[самокритика]
Тему не читай Фигню отвечай [/самокритика] в jQuery сделано явно не так Но этот пример также позволяет работать с объектом jQuery как с массивом, и цепочные вызовы А вообще, что за вопросы - посмотрите как сделано в jQuery, благо его исходники открыты - и не морочьте голову людям function jQuery(array) { (array instanceof Array) ? [].push.apply(this, array) : [].push.call(this, array); this.push = function() { [].push.apply(this, arguments); return this; }; this.pop = function() { return new jQuery([].pop.apply(this)); }; return this; } jQuery.prototype = []; var a = new jQuery([1,2]); console.log(a); a = a.push(3,4).push(5,6); console.log(a); console.log(a.pop()); |
ок, спасибо всем за помощь.
|
Цитата:
function jQuery( selector, context ) { return new jQuery.prototype.init( selector, context ); } jQuery.prototype = { constructor: jQuery, init: function( selector, context ) { this.selector = selector; return this; }, length: 0, selector: "", toString: function() { return "[" + this.selector + "]"; // вот это ФФ наверно и считывает при выводе в консоль } } jQuery.prototype.init.prototype = jQuery.prototype; console.log( jQuery("#someID") ); alert( jQuery("#someID") ); |
Цитата:
<script src="http://code.jquery.com/jquery-1.7.2.js"></script> <script> alert( $().toString ); </script> Цитата:
======================= Кратко ======================= Смешивает список найденных элементов с текущим (возвращаемым) объектом jQuery.
К первому немного кода: var current_jq = { }; var finded_elemenets = document.getElementsByTagName("div"); // т.к. nodelist - живой массив, замораживаем его, с помощью превращения в обычный массив. finded_elements = [].slice.call(finded_elements, 0); // переносим значения из результатов поиска в текущий экз. // так работает Array.prototype.push for(var i = 0; i < finded_elements.length; i++) { // узкий момент. тут не по документации, я просто сократил несколько вызовов до одного. if (!isNumeric(current_jq.length)) { current_jq.length = +0; } current_jq[i] = finded_elements[i]; current_jq.length++; } function isNumeric(variable) { return !isNaN(parseFloat(variable, 10)) && isFinite(variable); } *к коду сверху* С чего ты взял, что push работает именно так ? Cм документацию. Если не понятно - могу разжевать. ======================= Подробно : ======================= $.fn.init (она вызывается при $(), знаем же?) вызывает поиск Sizzle (эта штучка ищет элементы по селектору, если кто не в курсе), указывая помимо всего аргумент с именем "extra" - это объект, куда Sizzle подмешает в конце результаты поиска. Sizzle живёт в самой jQuery с именем find. (вызвать можно так : jQuery.find(bla bla bla)) В конце своём сиззл вызывает функцию makeArray, передавая ей такие аргументы : первый - NodeList найденных элементов, второй - объект (тот самый extra). её исходный код : // array - найденные элементы // results - jQuery объект, который будет возвращён. var makeArray = function( array, results ) { array = Array.prototype.slice.call( array, 0 ); if ( results ) { results.push.apply( results, array ); return results; } return array; }; что за метод push у объекта jQuery ? да самый обычный пример заимствования методов - т.е. это метод не самописный, а взятый у массивов. <script src="http://code.jquery.com/jquery-1.7.2.js"></script> <script> alert( $().push ); </script> можем убедиться в коварстве сиззла, подсунув ему что-нибудь своё : <script src="http://code.jquery.com/jquery-1.7.2.js"></script> <p>SAMPLE</p><div>LOL</div> <script> var extra = { push: function(/*elements*/) { for(var i = 0, args = arguments; i in args; i += 1) { alert("Push добавляет : "+args[i]+"\n\nСтарая длина : "+this.length); this[this.length++] = arguments[i]; } }, length: 0, context: document } jQuery.find("p, div", document, extra); </script> PS уморился. |
Часовой пояс GMT +3, время: 08:18. |