Tip Code
78 subscribers
13 photos
2 videos
4 links
تیپ هایی (Tip) از زبان های برنامه نویسی، فریمورک‌ها، پلتفرم‌ها، IDEs و ...

اکانت ما روی توئیتر:
Twitter.com/TipCode_ir
Download Telegram
چرا در #javascript باید یجای اپراتورهای '==' و '===' از ()Object.is استفاده کنیم؟

به خروجی این شرط ها نگاه کنید:
0 == ' ' //true
null == undefined //true
[1] == true //true

شاید برای حل این مشکل از اپراتور '===' بجای '==' استفاده می کنید اما این راه حل همه جا جواب نمیده، بعنوان مثال:
NaN === NaN //false

در حالیکه خروجی ()Object.is برای تمام موارد مقدار قابل قبول تری هست:

Object.is(0 , ' '); //false
Object.is(null, undefined); //false
Object.is([1], true); //false
Object.is(NaN, NaN); //true

#سطح_متوسط
👍1
استفاده از اپراتور + قبل از مقادیر در #javascript معادل استفاده ار تابع ()Number است:

0 === Number(null); // true

خروجی مقادیر پایین معادل خروجی تابع ()Number بجای اپراتور + است:

console.log(+'123'); // 123
console.log(+null); // 0
console.log(+true); // 1
console.log(+false); // 0
console.log(+[]); // 0
console.log(+[123]); // 123
console.log(+new Date); // 1527790306576

#سطح_مبتدی
👍1
یک مثال از کاربرد تیپ قبلی: زمانی که نیاز به مقایسه مقادیر با ورودی های یک وب فرم مثل المنت های input، select و ... هستیم.

let today = new Date();
if (+form.month.value == (today.getMonth() + 1) &&
+form.day.value == today.getDate()) {
// happy birthday 🎂
// ...
}

#سطح_مبتدی #javascript
روشی جالب برای استفاده از دستور Switch Case در #PHP

$age = 15;

switch (true){
case ($age >= 1 && $age <= 12):
echo 'Child';
break;
case ($age >= 13 && $age <= 19):
echo 'Teenager';
break;
case ($age >= 20):
echo 'Adult';
break;
}

#بک‌اند #سطح_متوسط
حذف مقادیر تکراری از آرایه بدون استفاده از حلقه ها : #javascript

روش اول:
let noDupe = (arr) => 
arr.filter((item, i) =>
arr.indexOf(item) >= i);

ٰروش دوم: استفاده از Set و #spread_operator که در ES2015 اضافه شده اند ( برای کار در IE و یا نسخه های پایین Firefox و Chrome نیاز به transpiler دارید)

const noDupe = arr => [...new Set(arr)];

خروجی هر دو روش:
noDupe([1,2,2,1,3]); //[1,2,3];


#سطح_متوسط #spread_syntax
در #php برای پردازش یک آدرس #URL نیازی به نوشتن #Regex نیست و میتوان از توابع موجود استفاده کرد.
برای بدست آوردن قسمت های مختلف یک آدرس URL میتوان از دستور زیر استفاده کرد:

$url = 'http://example.com/path1/path2?var1=1000&var2=ali';
$parsed = parse_url($url);
// Output:
// array (
// 'scheme' => 'http',
// 'host' => 'www.example.com',
// 'path' => '/path1/path2',
// 'query' => 'var1=1000&var2=ali'
// )

یا اگر فقط قسمت خاصی از URL را نیاز داشتید:
$parsed = parse_url($url, PHP_URL_HOST);
// Output: example.com

#بک‌اند #سطح_متوسط
Tip Code
در #php برای پردازش یک آدرس #URL نیازی به نوشتن #Regex نیست و میتوان از توابع موجود استفاده کرد. برای بدست آوردن قسمت های مختلف یک آدرس URL میتوان از دستور زیر استفاده کرد: $url = 'http://example.com/path1/path2?var1=1000&var2=ali'; $parsed = parse_url($url);…
همچنین برای پردازش QueryString نیز میتوان از توابع داخلی #php استفاده کرد:

$url = 'http://www.example.com/path1/path2?var1=1000&var2=ali';
$query = parse_url($url, PHP_URL_QUERY);
parse_str($query, $params);
var_dump($query);
var_dump($params);

// Output1: var1=1000&var2=ali

// Output2:
// array (
// 'var1' => '1000',
// 'var2' => 'ali',
// )

#بک‌اند #سطح_متوسط
گارانتی تکرار درست تایمرها در #javascript

از اونجایی که کلیه دستورات 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 و یا بیشتر برسد.
سلکتور چشم جغد
در #css سلکتوری وجود دارد به نام چشم جغد که این صورت تعریف میشود:

* + * {
}

معنی: تمام المنتهایی که قبل از آنها المنت دیگری وجود دارد.
کاربرد: معمولا margin-top با border-top به عناصر یک لیست.
مثال:

.myList *+* {
margin-top: 1em;
}
#سطح_متوسط
This media is not supported in your browser
VIEW IN TELEGRAM
بیشتر اوقات هنگام استفاده از #Console در #DevTools مرورگرها نیاز داریم از خروجی دستور قبلی در اجرای دستور بعدی استفاده کنیم. برای اینکار از _$ استفاده کنید

این دستور در هر سه مرورگر Safari، Firefox و Chrome قابل دسترس هست (در دیگر مرورگرها تست نشده)

#سطح_متوسط #javascript
برنامه نویسان #PHP نمی‌توانند بلافاصله بعد از ایجاد Instant از روی کلاس، به عناصر داخل آن دسترسی داشته باشند:
// syntax error
new myClass()->myMethod();

در عوض مجبور هستند که کد خود را در دو خط بنویسند:
$a = new myClass();
$a->myMethod();

اگر میخواهید عمل فوق را در یک خط انجام دهید، باید به این صورت عمل کنید:
(new myClass())->myMethod();

#بک‌اند #سطح_مبتدی
راه ساده تر و با خوانایی بالاتر بجای استفاده از شرط های متوالی در #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]();

#سطح_مبتدی
در #CSS میتوان از هر نوع کاراکتر یونیکد و ایموجی استفاده کرد و روی مرورگرهای مختلف محدودیتی ندارد.
گاهی برنامه نویسان برای هیجان انگیز شدن کدنویسی یا به نشانه اعتراض به تصمیمات مدیرانشان، تلاش میکنند از نام کلاس‌های غیر معمول استفاده کنند.

🔰 معروف‌ترین آنها، کلاس روح (شبح) یا Ghost است:
<style>
.👻 {
color: blue;
}
</style>

<div class="👻">
Mr. Ghost
</div>

🔰 نمونه ای دیگر:
<style>
.💩 {
color: brown;
}
</style>

<div class="💩">
I'm Angry!
</div>



#فرانت‌اند #سطح_پیشرفته
تکنیک Advanced Lazy Loading در #javascript

روش های مختلفی برای پیاده سازی تکنیک 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
گاهی اوقات در #php قصد داریم تا اعداد را به صورت 10k یا 25M نمایش دهیم. از تابع زیر میتوان برای این کار استفاده کرد:

function numberSuffix($input)
{
$suffixes = array('', 'K', 'M', 'B', 'T');
$suffixIndex = 0;
while (abs($input) >= 1000 && $suffixIndex < sizeof($suffixes)) {
$suffixIndex++;
$input /= 1000;
}
return ($input > 0 ? floor($input * 1000) / 1000 : ceil($input * 1000) / 1000) . $suffixes[$suffixIndex];
}

echo numberSuffix(15000);
// Output: 15K

#بک‌اند #سطح_متوسط
برای تعریف fragments در #react می تونیم از <> و </> بجای React.Fragment استفاده کنیم

class Comments extends React.PureComponent{
render() {
return (
<>
<h1>Title</h1>
<p>Paragraph</p>
<time>Time</time>
</>
);
}
}

معادل کد پایین هست

class Comments extends React.PureComponent{
render() {
return (
<React.Fragment>
<h1>Title</h1>
<p>Paragraph</p>
<time>Time</time>
</React.Fragment>
);
}
}

#سطح_متوسط
اگر در #php از تابع ()empty استفاده میکنید، ممکن است نتایج ناخواسته‌ای بدست بیاورید. این تابع در نسخه 5.4 به پایین php فقط برای مقایسه مستقیم متغییرهاست و نه یک عبارت محاسباتی.
مثال:
 empty(trim($name))  // Error in php 5.4.0

🔰 همچنین در صورتی که از Magic Methodهای get__ و set__ برای کلاس‌ها استفاده میکنید، ممکن است نتایج ناخواسته ای بگیرید.
مثال:
class classA
{
private $_x;
public function __set($key, $value) {
if ($key === 'x')
$this->_x = $value;
}
public function __get($key) {
if ($key === 'x')
return $this->_x;
else
return null;
}
}

$cls = new classA();
$cls->x = 'Amir';
var_dump(empty($cls->x));
// Output True 👈

$var = $cls->x;
var_dump(empty($var));
// Output False 👈



🔰 دلیل این اتفاق این است که ساختار دستور ()empty به این صورت است:
!isset($var) || $var == false
// Reference www.php.net

🔰 راه حل:
۱- برای رفع این مشکل در کلاس هایی که از Magic Methodهای get__ و set__ استفاده میکنید، همیشه باید isset__ را نیز پیاده سازی کرد.

۲- کلا از تابع ()empty استفاده نکنید و بجای آن از var$! یا var$!@ استفاده کنید.

#بک‌اند #سطح_پیشرفته
تیدیل NodeList به آرایه

احتمالا زیاد پیش آمده که خواسته باشید لیستی از المنت های DOM که با دستور ()document.querySelectorAll برگردانده شده اند را مرتب یا فیلتر کنید. برای اینکار مقدار بازگشتی این تابع که از نوع NodeList هست را به یک آرایه تبدیل کنید تا بتوانید از توابع آرایه ای مثل sort, reduce, map, filter و... استفاده کنید:

domElements = document.querySelectorAll("ul"); //NodeList

یک راه برای تبدیل به آرایه:
var arrayElements = [].slice.call(domElements); 

راه دوم برای تبدیل مقدار بازگشتی به آرایه:

var arrayElements = Array.from(domElements);

#javascript #سطح_متوسط
همانگونه که می‌دانید سلکتورهای #CSS به حروف کوچک و بزرگ حساس (Case Sensitive) است. یعنی سلکتور PANEL. با panel. فرق دارد. این امر برای Attribute Selectorها ایجاد مشکل میکند.
به عنوان مثال قصد داریم تمام لینک هایی که به سایت google ارجاع داده شده اند را انتخاب کنیم:
<a href="//google.com"></a>
<a href="//Google.com"></a>
<a href="//GOOGLE.com"></a>

سلکتور زیر فقط لینک اول را انتخاب میکند:
a[href*=google] {...}

برای اینکه این سلکتور به حروف کوچک و بزرگ حساس نباشد باید به این صورت نوشته شود:
a[href*=google i] {...}

#فرانت‌اند #سطح_متوسط
This media is not supported in your browser
VIEW IN TELEGRAM
تابحال براتون پیش اومده که نیاز به اضافه و یا ویرایش چند خط در #Devtools داشته باشید؟ مثلا تصمیم داشته باشید font-size در چند کلاس را دستکاری کنید.

برای اینکار از کلید Ctrl + Click ) Cmd+ Click) استفاده کنید تا همزمان چند cursor داشته باشید.

#سطح_متوسط