آموزش جاوا اسکریپت Java Script قسمت هفتم

1395/4/17 اکرم کریمی 996

در این جلسه قرار بر این شد که در مورد متد addEventListener و callback function ها توضیحاتی رو خدمتتون ارائه کنم.

addEventListener: با استفاده از متد addEventListener میتوان به یک المنت یک event handler اضافه کرد، بدون اینکه event handlerهای موجود overwrite شوند. پس شما به این وسیله می توانید به یک المنت تعداد زیادی event handler اضافه نمایید. (به تابعی که برای مدیریت کردن یک رویداد ایجاد می شود event handler می گویند)

برای نوشتن کد به صورت جاوااسکریپت بی آزار (unobtrusive javascript) از event listener ها استفاده می شود. زمانی که ما کدها را به شکل unobtrusive می نویسیم در واقع کدهای js را از HTML جدا میکنیم و دیگر نیازی به تعریف رویدادهایی مثل onclick درون یک تگ html نیست. مزیت دیگر این روش کدنویسی این است که شما مجبور بودید برای تعریف یک تابع برای مدیریت رویداد، آن تابع را به صورت مستقیم در فضای نام سراسری قرار بدهید و این امکان وجود داشت که نام تابع شما با تابع دیگری که در یک کتابخانه که به صفحه اضافه کردید یکی باشد و این مورد برای شما دردسر ساز می شد. اما با استفاده از addEventListener با این مشکل مواجه نیستیم.

فرمت کلی این دستور به شکل زیر است:

document.getElementById("myBtn").addEventListener("click", myEventHandler);

 

المنت مورد نظر رو انتخاب کرده و با دستور addEventListener تابعی که قرار است event handler ما باشد را به رویداد مورد نظر الصاق می کنیم. myEventHandler اسم تابع من برای مدیریت این رویداد است، می توان به جای استفاده از نام تایع، خود تابع را قرار داد:

 

document.getElementById("myBtn").addEventListener("click", function() {
 // some code
});


 

این دستور صرفا برای رویدادهای مربوط به عناصر html نمی باشد، بلکه برای تمامی اشیاء DOM از قبیل window نیز مورد استفاده است.

 

window.addEventListener("resize", function(){
 document.getElementById("demo").innerHTML = "sometext";
});

برای حذف یک eventListener به صورت زیر عمل می شود:

element.removeEventListener("myBtn ", myEventHandler);

مرورگرهای IE8 و قبل از آن و همینطور Opera6 و قبل از آن متدهای addEventListener و removeEventListener را پشتیبانی نمی کنند. رویداد جایگزین در این مرورگرها attachEvent و detachEvent می باشد. برای مدیریت این ناهماهنگی بین مرورگرها می توان به روش زیر عمل کرد:

var x = document.getElementById("myBtn");
if (x.addEventListener) { // For all major browsers, except IE 8 and earlier
x.addEventListener("click", myFunction);
} else if (x.attachEvent) { // For IE 8 and earlier versions
x.attachEvent("onclick", myFunction);
}

 

خب، با توجه به مطالبی که گفته شد، من میتونم کدم مربوط به stopwatch رو به صورت زیر تغییر بدم:

 

کد HTML:

<body>
 <div id="demo">0</div>
 <input id="btnStart" type="button" value="start" />
 <input id="btnStop" type="button" value="stop" />
</body>

 

کد JS:

 

document.addEventListener("DOMContentLoaded", function() {
 'use strict';

 // variables
 var s = 0;
 var myInterval;

 start();

 // eventListeners
 document.querySelector("#btnStart").addEventListener("click", start);
 document.querySelector("#btnStop").addEventListener("click", stop);

 // functions

 function start() {
 myInterval = setInterval(function () { document.querySelector("#demo").innerText = ++s; }, 1000);
 }
 function stop() {
 clearInterval(myInterval);
 }
});

 

حالا با این روش خیال من از چند لحاظ راحته اول اینکه اسم متغیرهام با یک کتابخانه دیگر، فایل script دیگر و کدهای JS درون صفحه تداخل پیدا نمیکنه.:) همینطور اسم توابعم، و اینکه مجبور نیستم تابع مرتبط با یک رویداد رو در فضای نام سراسری بنویسم، همینطور اینکه برای تغییر اسم یه تابع لازم نیست برم سراغ کد HTML ووووو

 

همه چیز رو میبرم داخل یک تابع، البته از این توابع زیاد میتونم داشته باشم.

تنها چیزی که باید بگم اینه که، من این کد رو همونطور که میبینید طوری ننوشتم که همه مرورگرها رو پشتیبانی کنه. حتی برای متد load مربوط به document.

Callback Function:

در کد نویسی ممکن است که بخواهیم کدهایی را درون یک تابع قرار دهیم و این فقط یک خروجی نداشته باشد، یک حالتش این است که من می توانم از مجموعه خروجی های این تابع یک شئ ایجاد کنم و آن شئ را به عنوان خرجی تحویل دهم، روش دیگری که من می توانم به آن صورت عمل کنم این است که کدهایی که مربوط به مواردی است که می خواهم از خرجی ها استفاده کنم را در تابع دومی قرار داده و ورودی های این تابع، خروجی های تابع اول باشد و تابع دوم را به عنوان یکی از پارامترهای ورودی تابع اول معرفی کنم. به تابعی که من آن را به عنوان پارامتر ورودی یک تابع دیگر تعریف کردم callback function می گویند. من می توانم چندین callback function را به عنوان ورودی به یک تابع پاس بدهم. شما این حالت را می توانید در متد ajax کتابخانه jquery ببینید.

نمونه دیگری که می توان مثال زد تابع setTimeout است که تابع دیگری را به عنوان ورودی دریافت میکند. ممکن است شما موارد بسیار دیگری نیز در نظرتان بیاید.

حالت دیگری که به نظرم می رسد این است که من قصد دارم یک تابع مجزا که ممکن است در جاهای دیگر نیز از آن استفاده کنم را بخواهم ورودی یک تابع قرار دهم، نمونه ای ساده از این حالت را بررسی می کنیم:

var allUserData = [];
 function logStuff (userData) {
 if ( typeof userData === "string")
 {
 document.write(userData);
 }
 else if ( typeof userData === "object")
 {
 for (var item in userData) {
 document.write(item + ": " + userData[item] + "<br>");
 }
 }
 }

function getInput (options, callback) {
 allUserData.push (options);
 callback (options);
}
 getInput ({name:"Rich", speciality:"JavaScript"}, logStuff);

 

در این مثال من دو تابع logStuff و getInput را دارم که در تابع اول یک ورودی رو میگیرد و بنا بر اینکه این نوع این ورودی string است یا object تصمیم میگیرد که از چه روشی برای نمایش آن در خروجی استفاده کند. تابع دوم یک ورودی را گرفته و به یک آرایه اضافه می کند و علاوه بر آن ورودی را به عنوان ورودی callback function می فرستد. فراخوانی این تابع را هم در فضای نام سراسری می بینیم. در فراخوانی تابع getInput پارامتر اول، یک شی و پارامتر دوم نام تابع logStuff را ارسال میکنیم. توجه کنید که در هنگام ارسال یک callback function، جلوی نام تابع پرانتز باز و بسته نگذارید که در این صورت در همان خط ارسال تابع callback اجرا خواهد شد. من مجددا می توانستم که خود تابع را به جای نام تابع ارسال کنم اما یک مقدار جلوه زشتی پیدا می کرد.

 

در این کد، حلقه for in را داریم که این حلقه فقط بر روی اشیاء قابل اجراست و مقداری که درون item پر میشود به عنوان اندیس در آن شئ است، مثلا در مرتبه اول مقدار آن برابر name و در مرتبه دوم برابر speciality خواهد بود. به همین دلیل من از طریق

می توانم به مقدار آن در سئ ورودی دسترسی داشته باشم.

یک آرایه سراسری allUserData هم داریم که با استفاده از متد push میتوانیم اشیاء جدید را به آن اضافه نماییم. در مورد کار با آرایه ها در جلسات آینده توضیح داده خواهد شد.

دانلود PDF قسمت هفتم آموزش جاوااسکریپ