گارانتی تکرار درست تایمرها در #javascript
از اونجایی که کلیه دستورات javascript تنها در یک thread اجرا می شوند، هیچگونه گارانتی برای اجرای دستورات ()setInterval در interval مشخص شده وجود ندارد. چرا که شاید مدت زمان اجرای دستورات داخل setInterval بیشتر از مدت زمانِ interval تعیین شده باشد و در این صورت تایمرهای بعدی به صف دستورات در javascript اضافه نخواهند شد تا کار تایمر قبلی تمام و از صف دستورات خارج شود.
همچنین ممکن است در بعضی موارد چند تایمر بلافاصله (بدون وقفه) بعد از هم اجرا شوند چرا که interval تعیین شده برای اجرای مجدد تایمر به مدت زمانِ صرف شده جهت اجرای دستورات داخل تایمر نزدیک بوده است.
برای حل این مشکل از دو دستور setTimeout و arguments.callee به شکل پایین استفاده می کنیم:
از اونجایی که کلیه دستورات javascript تنها در یک thread اجرا می شوند، هیچگونه گارانتی برای اجرای دستورات ()setInterval در interval مشخص شده وجود ندارد. چرا که شاید مدت زمان اجرای دستورات داخل setInterval بیشتر از مدت زمانِ interval تعیین شده باشد و در این صورت تایمرهای بعدی به صف دستورات در javascript اضافه نخواهند شد تا کار تایمر قبلی تمام و از صف دستورات خارج شود.
همچنین ممکن است در بعضی موارد چند تایمر بلافاصله (بدون وقفه) بعد از هم اجرا شوند چرا که interval تعیین شده برای اجرای مجدد تایمر به مدت زمانِ صرف شده جهت اجرای دستورات داخل تایمر نزدیک بوده است.
برای حل این مشکل از دو دستور setTimeout و arguments.callee به شکل پایین استفاده می کنیم:
setTimeout(function(){
// code
setTimeout(arguments.callee, interval);
}, interval);
برای دوستانی که از قبل با arguments.callee آشنایی ندارند: arguments.callee یک اشاره گر (Pointer) به تابع در حال اجرا است (بعبارت دیگر اشاره گر به تابعی است که مالک arguments است).یکی از کاربردهای تیپ قبلی در پیاده سازی انیمیشن ها در #javascript است چرا که انیمیشن باید بصورت نرم (smooth) اجرا شود و تاثیر انیمیشن قابل مشاهده باشد.
setTimeout(function(){
var div = document.getElementById('aDiv'),
right = parseInt(div.style.right) + 5;
div.style.right = right + 'px';
if (right < 150)
setTimeout(arguments.callee, 50);
}, 50);
این تایمر باعت حرکت div از راست به چپ در هر بار اجرای تایمر می شود تا زمانی که فاصله div از سمت راست به 150px و یا بیشتر برسد.This media is not supported in your browser
VIEW IN TELEGRAM
بیشتر اوقات هنگام استفاده از #Console در #DevTools مرورگرها نیاز داریم از خروجی دستور قبلی در اجرای دستور بعدی استفاده کنیم. برای اینکار از _$ استفاده کنید
این دستور در هر سه مرورگر Safari، Firefox و Chrome قابل دسترس هست (در دیگر مرورگرها تست نشده)
#سطح_متوسط #javascript
این دستور در هر سه مرورگر Safari، Firefox و Chrome قابل دسترس هست (در دیگر مرورگرها تست نشده)
#سطح_متوسط #javascript
راه ساده تر و با خوانایی بالاتر بجای استفاده از شرط های متوالی در #javascript
این کد را در نظر بگیرید:
این کد را در نظر بگیرید:
if (ch) {
if (ch === 'a') {
doA();
} else if (ch === 'b') {
doB();
} else if (ch === 'c') {
doC();
} else if (ch === 'd') {
doD();
} else if (ch === 'e') {
doE();
}
}
کد پایین کاری مشابه با تکه کد بالا انجام میده:var chObj = {
'a': doA,
'b': doB,
'c': doC,
'd': doD,
'e': doE
};
if (ch in chObj)
chObj[ch]();
#سطح_مبتدیتکنیک Advanced Lazy Loading در #javascript
روش های مختلفی برای پیاده سازی تکنیک lazy loading در بین برنامه نویسان متداول هست اما دراین تیپ (Tip) توضیح و کاربرد یکی از پیاده سازی های پیشرفته این تکنیک در #javascrip را می نویسم:
مثلا روش کلاسیک پایین را در نظر بگیرید که بیشتر برنامه نویسان جاواسکریپت در گذشته جهت بررسی امکانات مرورگر کاربران بمنظور پیاده سازی AJAX استفاده می کردند:
#سطح_پیشرفته #advanced_lazy_loading
روش های مختلفی برای پیاده سازی تکنیک lazy loading در بین برنامه نویسان متداول هست اما دراین تیپ (Tip) توضیح و کاربرد یکی از پیاده سازی های پیشرفته این تکنیک در #javascrip را می نویسم:
مثلا روش کلاسیک پایین را در نظر بگیرید که بیشتر برنامه نویسان جاواسکریپت در گذشته جهت بررسی امکانات مرورگر کاربران بمنظور پیاده سازی AJAX استفاده می کردند:
function createAjax() {
if (window.XMLHttpRequest) {
// code for modern browsers
return new XMLHttpRequest();
} else {
// code for IE6, IE5
return new ActiveXObject("Microsoft.XMLHTTP");
}
}
// Call the func
var xhttp = createAjax();
یعنی با هر بار اجرای این تابع شرط if...else احرا می شود در حالیکه خروجی این تابع در فراخوانی های بعدی تغییری نمی کند پس فقط نیاز به یکبار اجرای if..else و بقیه دستورات داریم به همین دلیل از روش Advanced Lazy laoding برای پیاده سازی این تابع استفاده می کنیم. دقت کنید که در این روش تایع در داخل بدنه خود overwrite می شود:function createAjax() {
if (window.XMLHttpRequest) {
createAjax = function() {
return new XMLHttpRequest();
}
} else {
createAjax = function() {
return new ActiveXObject("Microsoft.XMLHTTP");
}
}
return createAjax();
}
// call the func again the same old version
var xhttp = createAjax();
این تکنیک برای تابع هایی که به تعداد زیاد فراخوانی می شوند و خروجی آنها در فراخوانی های بعدی هیچگونه تغییری با فراخوانی اول ندارند استفاده می شود.#سطح_پیشرفته #advanced_lazy_loading
تیدیل NodeList به آرایه
احتمالا زیاد پیش آمده که خواسته باشید لیستی از المنت های DOM که با دستور
احتمالا زیاد پیش آمده که خواسته باشید لیستی از المنت های DOM که با دستور
()document.querySelectorAll برگردانده شده اند را مرتب یا فیلتر کنید. برای اینکار مقدار بازگشتی این تابع که از نوع NodeList هست را به یک آرایه تبدیل کنید تا بتوانید از توابع آرایه ای مثل sort, reduce, map, filter و... استفاده کنید:domElements = document.querySelectorAll("ul"); //NodeList
یک راه برای تبدیل به آرایه:var arrayElements = [].slice.call(domElements);راه دوم برای تبدیل مقدار بازگشتی به آرایه:
var arrayElements = Array.from(domElements);#javascript #سطح_متوسط
تفاوت دو تابع
قبل از استفاده از تابع
در حالیکه:
مقدار خروجی این دو تابع در موارد بالا با هم فرق میکنه چون تابع سراسری
#سطح_متوسط
()isFinite و ()Number.isFinite در #javascriptقبل از استفاده از تابع
()isFinite حتما مقدار ورودی را چک کنید، چون:isFinite(null); //true :(isFinite('1'); //true :(در حالیکه:
Number.isFinite(null); //false :)Number.isFinite('1'); //false :)مقدار خروجی این دو تابع در موارد بالا با هم فرق میکنه چون تابع سراسری
()isFinite ابتدا مقدار ورودی را به Number تبدیل می کند و مقدار Number(null) = 0 است.#سطح_متوسط
اگر فکر می کنید که همیشه می تونید اسم یک تابع را بعنوان callback به توابعی مثل map، که تابعی(callback) بعنوان ورودی دریافت می کنند، اشتباه می کنید.
#سطح_متوسط #javascript
#سطح_متوسط #javascript
👍1
به این دو تابع نگاه کنید! حروجی یکسانی باید داشته باشند؟
برای پیدا کردن قسمت هایی از کد که باید semicolon گذاشته بشه از یک ابزار lint مثل JSHint یا JSLint استفاده کنید
#سطح_مبتدی
function foo1() {
return {
bar: "Hello"
};
}
function foo2() {
return
{
bar: "Hello"
};
}
اما این دو تابع خروجی یکسانی ندارند:foo1(); // {bar: "hello"}
foo2(); // undefined
اگر چه گذاشتن semicolon در #javascript اختیاری هست اما باعث این دست از حطاها میشه که پیداکردنش زمانبره.برای پیدا کردن قسمت هایی از کد که باید semicolon گذاشته بشه از یک ابزار lint مثل JSHint یا JSLint استفاده کنید
#سطح_مبتدی
Jshint
JSHint, a JavaScript Code Quality Tool
مبادله (Swap) مقادیر دو متغیر بدون استفاده از متغیر کمکی #javascript
#سطح_مبتدی #destructuring_assignment
#سطح_مبتدی #destructuring_assignment
👍1
👍1
خیلی وقت ها لازم هست که برخی پارامترهای تابع داری مقدار باشند تا تابع به درستی کار کند. برای اجباری کردن این پارامترها از تکه کد پایین استفاده کنید:
#سطح_متوسط #javascript
const isRequired = (paramName) => {
throw new Error(
`param |${paramName || ''}| is required`
);
};
const aFunc = (fullname = isRequired("fullname")) => {
console.log(`hello ${fullname}`);
};
هر دوی این دستورات باعث خطا می شود:aFunc();اما این دستورات به درستی اجرا می شوند:
aFunc(undefined);
aFunc('unknown');
aFunc(null);
برای اجرای این تکه کد در مرورگرهای قدیمی که هنوز arrow functions و مقدار پیش فرض برای پارامترها را ساپورت نمی کنند نیاز به transpiler دارید#سطح_متوسط #javascript
زیاد پیش میاد که وجود یا عدم وجود یک زیررشته را چک کنیم. برای اینکار از
این تیپ با استفاده از اپراتور
کاربرد:
()indexOf و مقایسه با عدد 1- استفاده می کنیم.این تیپ با استفاده از اپراتور
~ کار رو ساده تر می کنه:String.prototype.includes =
function (search, start) {
return !!~this.indexOf(search, start);
}
بدلیل نمایش 32بیتی اعداد در جاوااسکریپت، 1-~ و 4294967295~ (1 - 32 ^ 2) برابر با 0 هستندکاربرد:
"TipCode".includes("T"); //true
"TipCode".includes("T", 1); //false
#سطح_متوسط #javascriptیکی از ویژگی های پرکاربرد که سال ها قبل به #ES2015 اضافه شد و بیشتر موتورهای #javascript و مرورگرها ساپورت می کنند، معرفی Template literals بود. رشته هایی (string) که با استفاده از کاراکترهای
#سطح_مبتدی
`` بجای " یا ' تعریف می کنیم. با استفاده از این ویژگی می تونیم رشته ها را قالب بندی کنیم و رشته های چند سطری داشته باشیم:var name = 'foo';
console.log(
`Go to the next two lines
print ${name}!`);
// Output:Go to the next two lines
print foo!#سطح_مبتدی
Tip Code
یکی از ویژگی های پرکاربرد که سال ها قبل به #ES2015 اضافه شد و بیشتر موتورهای #javascript و مرورگرها ساپورت می کنند، معرفی Template literals بود. رشته هایی (string) که با استفاده از کاراکترهای `` بجای " یا ' تعریف می کنیم. با استفاده از این ویژگی می تونیم…
Tag Functions - #javascript
امکان پیشرفته تری که Template literals فراهم می کنند، قابلت Tagged templates هستند. تگ ها امکان پارس کردن template literals را از طریق توابع (Tag functions) فراهم می کنند.
نحوه صدا زدن این توابع فرق می کنند ( بدون پرانتز) و مقدار ورودی این تابع به این شکل پارس میشه: پارامتر اول آرایه ای از مقدار رشته ها (strings) و پارامترهای یعدی متغیر های استفاده شده در رشته هستند:
امکان پیشرفته تری که Template literals فراهم می کنند، قابلت Tagged templates هستند. تگ ها امکان پارس کردن template literals را از طریق توابع (Tag functions) فراهم می کنند.
نحوه صدا زدن این توابع فرق می کنند ( بدون پرانتز) و مقدار ورودی این تابع به این شکل پارس میشه: پارامتر اول آرایه ای از مقدار رشته ها (strings) و پارامترهای یعدی متغیر های استفاده شده در رشته هستند:
let Person = {
name: 'foo',
age: 30
};
function tag(str,name, age) {
console.log('output:');
console.log(str[0]);
console.log(str[1]);
console.log(name);
console.log(age);
};
let {name, age} = Person;
/*
Tagged template is a function call
that get its arguments from a
template literal.
*/
tag`Name: ${name}, age:${age}`;
// output:
// Name:
// , age:
// foo
// 30
#سطح_پیشرفته❤1
روش ساده تر برای حذف یک آیتم از آرایه با حفظ #immutability در #javascript
const newArr =
[...arr.slice(0, index),
...arr.slice(index + 1)];
#سطح_متوسط #immutableسریعترین راه تبدیل Float به Int
console.log( 12.9 | 0); // 12
console.log(-12.1 | 0); //-12
console.log(~~12.1); //12
console.log(~~-12.1); //-12
#javascript #سطح_متوسط👍2
با این کد ساده، پاس دادن مقدار برای پارامترهای تابع را در #javascript اجباری کنید!
const isRequired = (argName) => {
throw new Error(`|${argName}| is a required arg!`);
};
استفادهconst aFunc = (name = isRequired('name')) => { /* body */ };
نتیجه// Error: name is a required arg!
aFunc();
aFunc(undefined);
// No error
aFunc('TipCode');
aFunc(null);
@TipCode👍1
اپراتور "
بعضی از دولوپرها از این شکل استفاده می کنند چون علامت
<--" در #javascript چه کاری میکنه؟!let x = 10;
while(x --> 0)
console.log(x);
با استفاده از امکان space بین اپراتورهای ++ , -- و اپرند، <-- فقط تلفیق دو اپراتور -- و < هست.بعضی از دولوپرها از این شکل استفاده می کنند چون علامت
<-- از نظر بصری مثل اشاره گر به عدد انتهایی هست.👍1
const name = 'foo', family = 'bar';برای راحت دیباگ کردن از Object Initializer استفاده کنید:
console.log({name, family});
بجای:console.log(`name: ${name}, family: ${family}`);
#javascript