Saeed_Shamsi 758 ارسال شده در بهمن 89 کمي بيشتر همراه با DOM jQuery باز هم بهترين گزينه خواهد بود اگر تصور شما بر آن است که تمام کاري که جاوااسکريپت انجام مي دهد به "بده بستان" با صفحه ختم مي شود. اين موضوع زماني نمود پيدا مي کند که اين سيستم قدرتمند معمولا ظاهري شبيه به برنامه نويسي هاي معموال را ندارد. فعاليتهاي ديگر در جاوااسکريپت هم توسط اين سيستم قابل اجراست ولي اگر تمرکز و فوکوس شما روي DOM ،CSS، متحرک سازي، دريافت اطلاعات توسط AJAX است، jQuery اين مسئله را پوشش مي دهد در حاليکه نياز به سبک معمولي و دمده جاوااسکريپت هم نباشد. jQuery متدهايي را براي موارد غير از DOM نيز ارائه مي دهد؛ مانند روشي که براي شمارش آرايه ها دارد - (each(array, fn.$ – يا متدي براي پالايش رشته ها - (trim(str.$ . اما وجود اکثر اين متدها چندان حياتي نيستند وقتي فعاليت روي DOM و دسترسي به اجزاي آن انجام مي شود (از قبيل کار با CSS، مديريت اطلاعات HTML و تعريف رويداد هنگام کليک شدن بخشي از صفحه و غيره). اما اگر عميقتر به آن نگاه کنيد متوجه خواهيد شد که jQuery تمرکزي روي فعاليتهاي خارج از DOM ندارد. اين يکي از دلايلي است که يادگيري ساده آن را به ارمغان آورده ولي محدوديت در نگارش جاوااسکريپت هم با آن همراه شده. اين توجيهي است که او تمايلي به حرکت از يک سيستم خشک مختص DOM را ندارد. او از خواص ارث بري و حتي امکانات ابتدايي محلي براي متغيرهاي جاوااسکريپت محروم است، در واقع او نيازي هم به آنها ندارد. اگر نياز به استفاده از regular expressions، arrays، strings، dates، functions را داريد، جاوااسکريپت کمک شما خواهد بود. jQuery براي شما DOM را به يک زمين بازي تبديل مي کند ولي ساير فعاليتها در حيطه تعريف آن نيستند. اين نکته اي است که MooTools را کاملا متمايز مي سازد. به غير از تمرکز انحصاري روي DOM، گستره اين فريم ورک به کل زبان جاوااسکريپت مي رسد (بايد اضافه کرد که براساس تجربه اي که من با jQuery داشته ام، تمام فعاليتهاي ممکن با jQuery، با MooTools هم قابل اجراست ولي به شکلي کاملا متفاوت). اگر jQuery محيط DOM را به زمين بازي شما مبدل مي کند MooTools خود زبان جاوااسکريپت را زمين بازي شما مي کند و اين يکي از دلايلي است که يادگيري اش را مشکلتر ساخته. ارث بري يا Inheritance در جاوااسکريپت زبان جاوااسکريپت داراي قابليتهاي فوق العاده اي است. براي تازه کارها، اين زبان براساس توابع يا functional است به اين معنا که توابع به عنوان اشياء رده بالايي اجرا ميشوند که امکان ارسالشان بصورت متغير وجود دارد مانند اشياء String و Number و غيره. اين زبان با همين مفهوم ذهني طراحي شده و زماني که از اين روش استفاده مي کنيد اکثر متدها و الگوها(Patterns) بخوبي کار مي کنند. به اختلاف بين دو مورد زير توجه کنيد: for (var i = 0; i < myArray.length; i++) { /* do stuff */ } for (var i = 0; i < myArray.length; i++) { /* do stuff */ } و myArray.forEach(function(item, index) { /* do stuff */ }); myArray.forEach(function(item, index) { /* do stuff */ }); جاوااسکريپت داراي يک مدل ارث بري است. اين مدل با اينکه منحصر به فرد نيست ولي کم نظير است. در اين زبان بجاي تعريف کلاس و نمونه گيري آن، ارث بري بصورت prototypal صورت مي گيرد. بدين معنا که اشياء مستقيما از اشياء ديگر بدست مي آيند (به ارث مي رسند – inherit مي شوند). اگر در يک شيء، مشخصه يا Propertyاي درخواست گردد، جاوااسکريپت به دنبال آن در شيء فرزند (Child) جستجو مي کند و اگر پيدا نکرد جستجو را در شي والد (Parent) ادامه مي دهد. به همين دليل است که يک آرايه، به هنگام تعريف مي تواند متدهاي آرايه ها را بپذيرد: [1,2,3].forEach(function(item) { alert(item) }); //this alerts 1 then 2 then 3 [1,2,3].forEach(function(item) { alert(item) }); //this alerts 1 then 2 then 3 متدي با عنوان "forEach" براي آرايه بالا تعريف نشده پس جاوااسکريپت به دنبال اين متد در شيء والد يعني شيء Arrays مي گردد. وقتي اين متد را براي شيء از نوع آرايه بکار مي بريد، اين زبان، در شيء شما، اين متد را درخواست مي کند و اگر متدي با اين نام وجود نداشت، به سراغ متدهاي شيء مخصوص همه آرايه ها مي رود. اين بدين معناست که متد forEachدر حافظه مربوط به شيء بالا قرار نگرفته بلکه در حافظه مربوط به شيء اصلي آرايه ها (prototype of arrays) جاي دارد. اين يک شيوه فوق العاده کارآمد و مفيد است (شايان گفتن است که متد each در MooTools متناظر با متد forEach است). مرجع دروني يا Self refrence جاوااسکريپت يک عبارت خاص دارد: “this”. تعريف اجمالي اين عبارت براي من کمي مشکل است ولي در کل مي توان گفت اين عبارت در يک متد، به شيءاي که متد در آن واقع است اشاره دارد. اين قابليت به اشياء امکان ارجاع به خودشان را در متدهايشان مي دهد و کاربرد ديگري ندارد. اهميت اين ويژگي اينجاست که وقتي شما اشياء فرزند و نمونه هاي متعددي از آنها را داشته باشيد چطور متدها را، به شيء خودشان ارجاع مي دهيد؟ وقتي متد در کلاس والد وجود داشته باشد و در کلاس فرزند نباشد، اين عبارت امکان ارجاع به متد اصلي را به نمونه ها مي دهد (توضيحات تفصيلي درباره عبارت this و مقاله اي ديگر در موزيلا). عبارت this به اشيايي که به ارث برده شده اند، امکان ارجاع به متدهاي خودشان را مي دهد. اما گاهي پيش مي آيد که شما نياز به ارجاع به مکان ديگري از طريق this را داريد که در اين حالت بايد از binding استفاده شود. binding مقدار متفاوتي را براي this در متد مشخص مي کند. متد each از طريق پارامتر دوم خود امکان تعيين منبع شيء را فراهم مي کند. به مثال زير توجه کنيد: var ninja = { weapons: ['katana', 'throwing stars', 'exploding palm technique'], log: function(message) { console.log(message); }, logInventory: function() { this.weapons.each(function(weapon) { //we want "this" to point to ninja... this.log('this ninja can kill with its ' + weapon); }, this); //so we pass "this" (which is ninja) to Array.each } }; ninja.logInventory(); //this ninja can kill with its katana //this ninja can kill with its throwing stars //this ninja can kill with its exploding palm technique var ninja = { weapons: ['katana', 'throwing stars', 'exploding palm technique'], log: function(message) { console.log(message); }, logInventory: function() { this.weapons.each(function(weapon) { //we want "this" to point to ninja... this.log('this ninja can kill with its ' + weapon); }, this); //so we pass "this" (which is ninja) to Array.each } }; ninja.logInventory(); //this ninja can kill with its katana //this ninja can kill with its throwing stars //this ninja can kill with its exploding palm technique در مثال بالا و در متد logInventory ، ما ninja را به متدي که به آرايه منصوب شده ارجاع داديم که مي تواند عمليات log را بر روي خود ninja انجام دهد در حاليکه اگر با استفاده از پارامتر دوم each، شيء را به اصطلاح bind نمي کرديم، عبارت this همچنان به window اشاره مي داشت. اينها نمونه هايي از روشهاي قدرتمند جاوااسکريپت براي ارث بري، ارجاع دروني و binding و مشخصه هاي سودمند prototype بودند. نکته نامطلوب اين است که جاوااسکريپت اين امکانات را بطور کامل و سودمند ارائه نمي دهد و اينجاست که MooTools جلوه نمايي خواهد کرد. MooTools اين الگوها را بسيار ساده و دلپذير در دسترس قرار مي دهد. شما مي توانيد کدهاي خود را با کدهاي abstract بيشتري توليد کنيد (مترجم: الگوي abstract امکاناتي براي معرفي منابع ارجاعات به کدها را فراهم مي کند) که در يک اجراي طولاني، بسيار قابل استفاده و قدرتمند نمايان مي شود. فهميدن اينکه الگوها چطور مي توانند مقدارپذير (valuable) باشند و چطور بايد از آنها استفاده کرد به کمي تلاش نيازمند است اما در نهايت کدهاي شما بطور فوق العاده اي چندبار مصرف (reusable) و قابل مديريت مي شود. درباره اين دو خصوصيت در ادامه بحث خواهد شد. MooTools جاوااسکريپت را لذتبخش تر مي کند از آانجاييکه تمــرکز MooTools بر روي APIهاي جاوااســکريــپت است، اين زبان را پايدارتر و منسجم تر مي کند. اين فريم ورک تلاش زيادي براي تغيير شيوه کدنويسي نمي کند بلکه فوکوسي ويژه براي دلپذيرتر و قابل تحملتر کردن جاوااسکريپت دارد. مي توان گفت در واقع MooTools يک extension يا توسعه براي زبان جاوااسکريپت است. سعي او بر آن است که جاوااسکريپت را به موقعيتي که بايد باشد برساند. بخش اعظم هسته آن به تقويت اشياء Function، String، Array، Number، Element و غيره اختصاص دارد و بخش ديگر امکاني مهمي که ارائه مي دهد تابعيست با نام Class. حالا Classشباهت بيشتري به روشهاي تعريف الگوهاي ارث بري که در زبانهايي مثل Java يا ++C سراغ داريم، دارد اما اين همه موضـــوع نــيست. کاري که Class انجام مي دهد دسترسي و استفاده آسان از مدل ارث بري prototypal است (مترجم: شيء گرايي در بسياري از زبانها بر پايه تعريف کلاس است و در جاوااسکريپت بر پايه prototype به معناي دسترسي و ارتباط نمونه هاست). اين خواص توسط MooTools معرفي نشده اند و منحصر به فرد نيستند اما jQuery فاقد هر دوي آنهاست. jQuery هيچ مدلي براي ارث بري ندارد و امکاناتي هم براي اشياء محلي مثل String و Array تعريف نکرده. اين يک کاستي ساده نيست که نويسندگان jQuery به سادگي جبران کنند در واقع مي توان گفت آنها ابزاري طراحي کرده اند با مقاصد متفاوت. همانطور که MooTools جاوااسکريپت را مفرح مي سازد، jQuery نيز کار با DOM را دلپذيرتر مي کند و آنها با اين ديدگاه، محدوديتهاي خود را پذيرفته اند. jQuery استفاده از DOM را لذتبخش تر مي کند و اين دليل قابل دسترس تر بودن jQuery است. او از شما فراگيري جاوااسکريپت را نمي خواهد. او شما را به اعماق مدلهاي ارث بري و کاربرد this و binding و اشياء محلي پرتاب نمي کند. وقتي از طريق آموزش رسمي خود jQuery، به يادگيري آن اقدام مي کنيد، اين اولين مثالي است که آورده شده: window.onload = function() { alert("welcome"); } window.onload = function() { alert("welcome"); } و اين سومين است: $(document).ready(function() { $("a").click(function(event) { alert("Thanks for visiting!"); }); }); $(document).ready(function() { $("a").click(function(event) { alert("Thanks for visiting!"); }); }); اگر فراگيري MooTools را از طريق کتاب آن يا آموزش اينترنتي آن (که مؤلف هر دوي آنها من هستم) آغاز کنيد، خواهيد ديد که شيوه معرفي کاملا متفاوت است. با اينکه در آموزش MooTools امکان ناديده گرفتن ترتيب مباحث وجود دارد و مي توان مستقيما سراغ افکتها و بخشهاي DOM رفت ولي اين آموزش با طرح چيزهايي مانند Class يا پرسيدن سوالاتي از قبيل آيا شما يک برنامه نويس مبتدي هستيد يا آيا فقط قصد اضافه کردن امکاناتي به سايت خود هستيد، شروع مي شود. با اين وضعيت، jQuery براي شما بسيار دوستانه تر است. به عبارت ديگر اگر قصد يادگيري خود زبان جاوااسکريپت را داريد، MooTools بهترين وسيله است. او امکاناتي را معرفي مي کند که زبان جاوااسکريپت در حال حرکت به سمت آنهاست (بسياري از متدهاي Native در جاوااسکريپت 1.8 و بالاتر معرفي خواهند شد). اگر به برنامه نويسي آشنا هستيد مخصوصا به مدلهاي شيء گرايي و تابعي (functional)، فريم ورک MooTools الگوهاي طراحي شگفت انگيز و فوق العاده زيادي را داراست. هر کاري که تو بتوني، من بهترش رو مي تونم اغلب به ازاي امکاناتي که jQuery ارائه داده است نمونه مشابهي در MooTools يافت مي شود. اما اين ويژگي براي jQuery صادق نيست و بسياري از امکانات MooTools را نمي توان در jQuery شبيه سازي کرد زيرا همانطور که گفته شد، تمرکز آن بر روي DOM قرار دارد. دامنه امکانات MooTools از jQuery بيشتر است ولي شما از استفاده گسترده تر منع نشده ايد. براي مثال jQuery فاقد سيستم ارث بري است اما اين مشکلي نيست زيرا مي توانيد از قابليت Class موجود در MooTools بصورت تلفيقي در jQuery بهره ببريد (يا چنين قابليتي را خودتان در jQuery طراحي کنيد) و يا حتي از پلاگين مخصوص ارث بري در آن استفاده کنيد (من از اين پلاگين استفاده نکرده ام ولي اينطور به نظر مي رسد که قابليتهاي خوبي براي اين منظور داشته باشد). اگر به مثال ذيل از jQuery دقت کنيد: $(document).ready(function() { $("a").click(function(event) { alert("Thanks for visiting!"); }); }); $(document).ready(function() { $("a").click(function(event) { alert("Thanks for visiting!"); }); }); و آن را به MooTools ترجمه کنيد، خواهيد داشت: window.addEvent('domready', function() { $$('a').addEvent('click', function(event) { alert('Thanks for visiting!'); }); }); window.addEvent('domready', function() { $$('a').addEvent('click', function(event) { alert('Thanks for visiting!'); }); }); شباهت زيادي دارند، اينطور نيست؟ اين يک مثال پيچيده تر از jQuery است: $(document).ready(function() { $("#orderedlist li:last").hover(function() { $(this).addClass("green"); }, function() { $(this).removeClass("green"); }); }); $(document).ready(function() { $("#orderedlist li:last").hover(function() { $(this).addClass("green"); }, function() { $(this).removeClass("green"); }); }); و در MooTools داريم: window.addEvent('domready',function() { $$('#orderedlist li:last-child').addEvents({ mouseenter: function() { this.addClass('green'); }, mouseleave: function() { this.removeClass('green'); } }); }); window.addEvent('domready',function() { $$('#orderedlist li:last-child').addEvents({ mouseenter: function() { this.addClass('green'); }, mouseleave: function() { this.removeClass('green'); } }); }); مجددا بسيار شبيه هستند ولي من مي توانم ثابت کنم که نسخه MooTools کد بالا، بسيار روشنتر است ولي اين بحث باعث طولاني تر شدن مقاله مي گردد. بصورت کوتاه، کد MooTools دو رويداد تعريف کرده يکي براي ورود ماوس (mouse enter) و يکي براي خروج ماوس (mouse leave) و براي هر يک متدي مشخص کرده در حاليکه کد jQuery فشرده تر مي باشد. متد hover آن دو پارامتر دريافت مي کند که اولي براي ورود ماوس و دومي براي خروج ماوس اجرا مي شود. من شخصا معتقدم که نمونه کد MooTools منطقي تر و گوياتر است ولي نه کاملا ملموس. کدهاي jQuery گاهي خيلي براي من مبهم مي شوند. از نگاه کردن متدها اغلب چيز زيادي بدست نمي آيد و تحليل آنها مشکل است. اين مي تواند به اين خاطر باشد که من با کدهاي MooTools مأنوس تر هستم و خواندن درک آنها براي من آسانتر است. اما نکته اي که در MooTools قابل ستايش مي دانم، نامگذاري مناسب متدها و کلاسهاست که تقريبا هميشه نام عمل با کارکرد آن متناظر است و کمترين شبهه در آن وجود دارد. شما در همه زبانهاي برنامه نويسي بايد به سراغ بخش آموزش آن برويد تا با نحوه استفاده و سينتکس کدها آشنا شويد ولي در MooTools کافي است تا با روش منسجم و پايدار APIهاي آن آشنا شويد. نقل قول به اشتراک گذاری این ارسال لینک به ارسال به اشتراک گذاری در سایت های دیگر