Best practices ها : بهترین روش هایی که در طول کد نویسی در یک زبان تجربه شده و به اشتراک گزاشته شده است و معمولا با چند هدف کلی میان و به اشتراک گزاشته می شوند که در ابتدا برای کاهش باگ ها و خطر ایجاد یک باگ در کد و دوم افزایش پرفورمنس و کاربری یک کد و سوم خوانایی یک کد
1 - اگر قرار هست که ما بیایم و یک مقدار ثابتی رو در داخل جایی بیایم و بریزیم و یک متغیر بریزیم و ازش استفاده بکنیم بهتر هستش که بیایم و از const ها استفاده کنیم چون مواردی هستند که از اون استفاده میکنیم و تغیری نمیکنن و نیازی به تغیر ندارند
2 - اگر مطمئن نیستین که متغیری که میخاهیم تعریف بکنیم نیازی که به صورت گلوبال تعریف بشود یا بحث هویستت در آن استفاده شود از کلمه var استفاده نکنیم و به جاش از let استفاده بکنیم و از var موقعی بیایم و استفاده بکنیم که می خاهیم یک متغیربه صورت گلوبال به وجود بیاریم
3 - هر موقعی خواستیم بیایم و از یک object استفاده بکنیم بهتر هستش به جای استفاده از new object با استفاده از { } بیایم و اون رو تولید بکنیم این نکته پیرامون آرایه ها هم هستش
4 - اگر قرار هست که بیایم و یک پراپرتی به یک object اضافه بکنیم و نام اون پراپرتی داخل یک متغیر دیگه هست یا توسط یک فانکشن دیگه بازگشت داده می شود نیایم واون رو در خارج شی امون تعریف کنیم و بعد اون رو attach کنیم به شی امون بلکه از computed property ها استفاده بکنیم
// به شیوه یزر استفاده نکنیم
const obj = { id : 5, name: 'sdfdsfds' }
obj[getKey('enable')] = true;
// به این شیوه استفاده بکنیم
const obj = { id : 5, name: 'sdfdsfds'
[getKey('enable')] = true
}
5 - اگر قرار شد که ما بیایم و از یک تابع در داخل object استفاده بکنیم به جای اینکه بیایم و نام فانکشت رو بنویسیم و بعد یک تابع رو به اون assign بکنیم به شیوه زیر .. ema d: functio بیایم و تابع رو به همراه نامش در داخل object امون تعریف اش بکنیم ( ) emadn
6 - اگر نیاز نیست اطراف نام پراپرتی های یک object از دابل کوشن یا سینگل کوتشن استفاده بکنیم استفاده نکنید دابل یا سینگل کوتشن ها برای کلمه هایی هست که از دو قسمت تشکیل شده اند
7 - وقتی ما در داخل object مقادیر shorthan property داریم همون مقادیر رو بیایم و در داخل آبجکت امون بزاریم ولی در اول پراپرتی هامون بیایم و قرارشون بدیم ( استفاده از متغیر های const )
8 - وقتی که میخایم بیایم و یک آرایه رو در داخل یک متغیر دیگه کپی بکنیم از spreads ها استفاده بکنیم که مقادیر داخل یک آرایه رو میشکوند به مقادیر داخلش
const itemCopy = [... items];
9 - هر موقع خواستیم بیایم و از یک iterable object یک آرایه رو بسازیم خوب است که یا از تابع ()Array.from استفاده بکنیم یا هم از spread ها استفاده بکنیم بهترین اش همون راه حل دومی هستش
iterable object ها object هستند که فانکشن های و iterable و next در داخل آن ها تعریف شده است و ما می توانیم مقادیر اون object رو روشون یک حلقه یا iterable داشته باشیم و بتوانیم آن هارو بخونیم
10 - در هنگام کار با رشته هایی که در داخل اشون یک متغیر رو دارند بهتر هستش که بیایم و از template string ها استفاده بکنیم
gunction sayHi(name) {
return ` How are you , ${name}? ` ;
}
11 - اگر قراره یک تابع ای داشته باشیم که در یک شرایطی یا تعریف اش تغیر میکند یا اصلا تعریف میشه حالا می گوید که به جای این که ما تعریف تابع رو به طور کلی بیاریم داخل شرط به شکل زیر که اشتباه هست
// bad
if( currentUser ) {
function test(){
console.log('nope.')
}
بلکه بهتر هستش اول یک متغیر خارج از شرط امون تعریف بکنیم و بعد که اون شرط امون محقق شد اون متغیر رو به عنوان function value بیایم و بهش assign کنیم و اضافه کنیم به شیوه زیر
let test ;
if (currentUser ){
test = () => {
console.log('Yup');
}
}
12 - اگر یک تابعی داریم که یکسری پارامتر به عنوان ورودی دارد اسم اون پارامتر هارو arguments نزاریم چون خود جاوااسکریپت برای همه توابع یک پارامتر به اسم آرگومنت می فرسته و اگر همنام باشد دیگه اون شی نداریم و از دستش می دهیم
13 - اگر ما تابع امون یک مقدار پیش فرض رو دارد برای گرفتن یک مقدار پیش فرض پیشنهاد میکنیم که اون رو در داخل پرانتز بیایم وبهش بدیم نه به صورت دومی
// good
function handlethings(ops = {}){ }
// bad
function handlethings(ops){
ops = ops || {}
}
// ایراد
function testFunc(a){
a = a || 1 ;
console.log(a);
}
testFunc(0);
که به جای یک مقدار 1 رو برامون بر می گردوند
14 - می گوید اگر در داخل توابع امون ما اومدیم و یکسری ورودی های یا پارامتر های آپشنال داشتیم اون ها رو آخر قرار بدیم و در ابتدای پارامتر هامون نیایم و بزاریم
15 - ما به هیچ عنوان نباید داده های ورودی یک تابع رو تغیر بدیم یا ویرایش کنیم بلکه بهتر هستش اول بیایم و اون هارو داخل یک متغیر قرار بدیم و چک اشون بکنیم
//bad
function f1(obj){
obj.key = 1 ;
}
//good
function f2(obj) {
const key = key in object ? obj.key : 1 ;
}
15 - برای دسترسی به پراپرتی های یک شی از . استفاده کنید به جای [ ' ' ]
16 - برای به توان رساندن بهتر هستش که بیایم و از ** استفاده کنیم به جای تابع pow که در ریاضی ها هستش
17 - موقعی که باید بیایم و یک متغیر تعریف کنیم بهتر هستش که هر متغیر رو در یک const or let or var بریزیم
و این هم باید بدونیم که بهتر هستش ابتدا متغیر های const و بعد متغیر های var قرار دهیم
نکته : وقتی ما در داخل یک تابع میایم و عملیات return رو انجام می دهیم بقیه کدمون اجرا نمیشه و کلن میاد بیرون از تابع و همیشه سعی کنیم یک تابع رو همیشه جایی بیایم و invoke اش بکنیم که نیاز داریم بهش
18 - استفاده از assignment های چندگانه
// bad
let a = b = c = 1;
// good
let a = 1;
let b = a;
let c = a;
19 - اگر ما متغیری داریم که در داخل یک مقدار boolean هستش لازم نیست که بیایم و در شرط از == استفاده کنیم همون خالی قرار بدیم کافی هستش
20 - اگر میخاید خالی بودن یا نبودن یک رشته چک بکنید هیچ وقت بدون شرط چک نکنید و سعی کنیم شرط بزاریم براش
// bad
if ( name ) {}
//good
if ( name ! == '' ) {}
21 - هر موقع که خواستید که بیاید و length یک آرایه رو چک بکنید حتما شرط رو برای اون قرار بدهید و شرط کامل براش قرار دهید
22 - اگر قراره یک شرط ترنری داشته باشیم ?: که مثلا به شیوه های زیر بود به این شکل رو به روش بیایم و جایگزین اش کنیم
const foo = a ? a : b ;
const foo = a || b ; جایگزین بالا
////////////////////////////////////////////
const bar = c ? true : false ;
const bar = !!c ; جایگزین بالا
////////////////////////////////////////////
const baz = c ? false : true ;
const baz = !c; جایگزین بالا
23 - در عبارت های طولانی که داریم حتما بیایم و از پرانتز ها استفاده بکنیم همچنین در داخل شرط ها همیشه سعی کنیم از آکولاد ها استفاده بکنیم مگر اینکه کلن یک خط کد داشته باشیم و else ها رو همیشه بعد از آکولاد ها بیایم و بنویسیم
24 - اگر در یک تابعی شرط داریم و در داخل اون شرط هم داریم یک چیزی رو return میکنیم و بعد از اون هم یک else دیگع داریم که داخل اون هم باز یک return داریم نیازی به نوشتن else پایانی برای بازگشت دادن هیچ اثیری ندارد و بهتر هستش که از اون استفاده نکنیم
// bad
function foo(){
if(x){
return x;
}else{
return y;
}
}
// good
function foo(){
if(x){
return x }
return y;
}
25 - اگر خواستیم یک چیزی رو بعد از یک متغیری بیایم و اجراش بکنیم بهتر هستش که اون رو در داخل یک if بیایم و قرارش بدیم تا این که از && استفاده بکنیم
// bad
! isRunnig && statRunnig();
// good
if(! isRunnig){
statRunnig()
}
26 - کامنت گزاری اگر یک چیزی نیاز بود که بیایم و اون خطا رو fix کنیم ولی الان زمانی برای حل اون مشکل نداریم بهتر هستش که بیایم و یک کامنت گزاری انجام بدیم و یک کلمه FIXME : براش قرار بدیم تا بعدا خوانا تر بشه و اگر قرار بود کلن اون کد رو بیایم و تغیری اش بدهیم بهتر هستش که از TODO استفاده بکنیم برای کامنت گزاری کردن
27 - برای casting کردن یک چیزی به رشته 4 روش وجو دارد که بهتر هست که از خود تابع string بیایم و استفاده کنیم و برای عددی ها هم از تابع Number استفاده بکنیم یا parseInt که پارامتر دومش هم تایین شده است
28 - نام گزاری توابع و ثابت ها و متغیر ها بهتر هستش به صورت Camel Case باشد
کلمه کلیدی this به object هایی که در آن قرار دارد اشاره میکند
1 - در متد ها یا توابع this به object پدرش اشاره میکند و اگر اومدیم و در داخل اون متد در ی امون خواستیم و از یک callback function استفاده بکنیم کلمه This در اون callback به گلوبال ما اشاره میکند
let testObject = { name : 'mehrdad' , list : [1,2,3,4,5] ,
testFunc : function(){
console.log(this.name);
this.list.forEach(function(elem){
console.log(this) })
}
}
که برای حل این مشکل که در کال بک به گلوبال اشاره میکنددو تا ره حل هست
یکی کافی است که بیایم و در خط
بالای اون به این شکل استفاده بکنیم
//let myObjThis = this; یک راه دسترسی به این کشل هست
this.list.forEach(function(elem){
console.log(this) })
}.bind(this));
2 - this به تنهایی به Global object اشاره میکند
console.log(this);
در داخل یک تابع معمولی هم کلمه this به گلوبال اشاره میکند
function test(){ console.log(this); }
test()
3 - در حالت strict mode در توابع undefined است دقیقا در مثال بالا اگر به صورت استریک مود باشد دیگه بهش دسترسی نداریم
نکته : ما از bind فقط در کال بک فانکشن ها می تونیم بیایم و استفاده بکنیم و در توابع مثل بالا اگر گیر کردیم باید بیایم و از راه حل تعریف متغیر استفاده بکنیم
4 - اگر ما بیایم و از رویداد های html استفاده بکنیم this به خود اون رویداد میاد و اشاره میکند
button id = "test1" کلیک کنید
function test(){ console.log(this); }
let b = document.getElementById("test1");
b.onclick = test
DOM : به ازای تمام المنت ها و محتوا های داخل صفحه HTML یک object داریم که به این object ها DOM می گویند که زیر مجموعه global object صفحه ی document محصوب و خود داکیومنت هم زیر مجموعه ی window می شوند در واقع دام میاد و یک ساختار سلسه مراتبی از object ها ایجاد میکند و مخفف Document object Model هستش و ساختار سلسله مراتبی object ها در دام به این صورت هستش که یک object اصلی به نام Event Target در اون وجود دارد و یک object در لایه پایین تر وجود دارد به نام node که از قبلی میاد و ارث بری میکند و بقیه object دیگه در دام از این نود میان و ارث بری میکنن مثل object های Text و Element و Comment و باز خود شی المنت میاد و تبدیل میشه به دو تا دسته بندی با نام های SVG element و Html Element ها و تمام تگ های صفحه امون هم میان و زیر مجموعه ی المنت های Html میشوند مثل input و body و ..
کار هایی که DOM انجام میدهد
1 - برای همه المنت های HTML یک object میاد و تعریف میکند
2 - به ازای تمام پراپرتی های المنت ها میاد و object ایجاد میکند
3 - متد هایی برای دسترسی المنت های HTML ایجاد میکند
4 - به ازای تمام المنت ها رویداد هایی ایجاد میکند
نکته : دام 3 تا object اصلی در آن وجود دارد html و body و head
BOM : در واقع object هایی هستند که رفتار های زمینه ای صفحه رو به ما نشون می دهند مثل navigator و screen و غیره
1 - DOM Navigation
استفاده از child Nodes : برای دسترسی به المنت های فرزند صفحه مون
let body = document.body ;
let myDiv = body.childNodes[5];
همچنین برای لاگ گرفتن از تمام فرزندان داخل یک دیو به شیوه زیر می توانیم بیایم و اقدام کنیم
let childCount = myDiv.childNodes.length;
for ( let i = 0 ; i < childCount ; i++ ) {
console.log(myDiv.childNodes[i] );
}
پیمایش در نود ها با استفاده از parent Node و next Sibling و previous Sibling می تونیم بیایم و استفاده بکنیم
ما با استفاده از ایدی می توانیم به پراپتی های المنت هامون دسترسی پیدا کنیم
table id="table1"
thead
tr
th ....
console.log(table1.id)
با استفاده از دستورات زیر می توانیم در نود جدول پیمایش داشته باشیم
table.rows // te.cells // tr.rowindex
table.caption/thead/tFoot
table.tBodies
console.log(table1.tBodies[0].rows);
نکته : گام اول کار کردن با کار گام نویگشن هستش که دو تا راه وجود دارد یکی گام نویگشن و دیگری گام سرچینگ هستش برای کار کردن با المنت هامون باید کار کردن با اون ها رو یاد بگیریم
اگر در هنگام نام گزاری آیدی هامون و دسترسی گرفتن از اون ها بیایم واز مدل هایفن مدل یا - استفاده بکنیم دام نمی تونه بیاد و شی اون رو بسازه و اون شی رو نداریم چون در نام متغیر ها نمی تونیم بیایم واز - استفاده بکنیم ( در اصل variable اون رو نمیتونه بیاد و بسازه اما ابجکت اون به عنوان آبجکت یکی از پراپرتی های اصلی window وجود دارد
و با استفاده از اون می تونیم بیایم و بهش دسترسی پیدا بکنیم
console.log(window['table2-test'])
پس یا ما نباید در نام از - استفاده کنیم و یا اگر این کار رو کردیم بیایم و به شیوه بالا از اون استفاده بکنیم
2 - DOM Searching : که به طور کلی دوتا راه داره یکی get Element ها و دیگری query Selector ها که با استفاده از یکسری پسوند تبدیل به یکسری توابع می شوند
document.getElementById('')
document.getElementByTagName('')
document.getElementByClassName('')
به غیر از اولی مابقی یک لیست رو برای ما بر میگردونند
کوری سلکتور میاد و اولین سلکتوری که با اون مشخصاتی که بهش دادیم رو برامون پیدا میکنه و بر می گردونه در هنگام استفاده از کوری ها به ما یک نودلیست رو تحویل می دهد
document.querySelectorAll('')
documentquerySelector('')
نکته : ما سه مدل object داشتیم که میومد و از node ها ارث بری میکردند یکی text ها دومی element ها سومی comment ها و ما با توابع searching فقط میتونیم المنت ها رو سرچ کنیم
که البته با یکسری ترفند از هردو روش میشه باز دسترسی داشت
تابع سرچ elem.matches(css) condition
به ما میگوید که بر اساس این تابع که بهت میدم میام و بهت میگم که آیا اون وجود دارد یا خیر و یک مقدار بولین به ما بر میگردوند
elem.closest(css)
در واقع به ما نزدیک ترین جد یا پدر اون المنت رو به ما بر می گردوند
نکته : همه توابع get Elements By لیست زنده ایجاد میکنند در صورتی که خروجی تابع های query یک لیست ایستا و بدون تغیر را ایجاد میکند
نکته برای ارث بری در المنت هامون یک عکس هم پایین پیوست هست
alert(document.body instanceof HTMLBodyElement); // true
alert(document.body instanceof HTMLElement); // true
alert(document.body instanceof Element); // true
alert(document.body instanceof Node); // true
alert(document.body instanceof EventTarget); // true
همان طور که قبلا گفته شد نود ها خودشون چند دسنه می شوند مثل text و element و comment و باز المنت ها هم خودشون چند دسته می شوند حالا برا اساس نوع اون المنت
text ها اشیایی هستند که برای رشته ها و space ها و متن هایی استفاده می شوند که داخل یک تگ نباشند
ویژگی های مشترک در همه نود ها
--------------------------------
1 - node Name ویژگی مشترک برای همه نود ها وجود دارد
2 - ویژگی tag Name هم فقط برای Element ها وجود دارد
برای المنت ها tag Name و node Name برابر است و باهم یکی هستش
کار با محتوای المنت ها inner HTML
-------------------------------------------------------
1 - متن داخل و کد داخل المنت را بر میگردونه
2 - قابلیت ویراش شدن دارد ( وقتی تغیرش بدیم میاد و کلن آپدیت میکنه خودش رو )
3 - اسکریپت داخل آن قرار میگیرد ولی اجرا نمی شود
4 - محتوا را به طور کامل بازنویسی میکند
5 - ابتدا محتوای جدید را می نویسید درنتیجه تمام منابع مثل عکس ها مجددا بارگزاری می شوند
تفاوت inner HML با outer HTML که دومی المنت را ویرایش نمی کند بلکه آن را جایگزین میکند و در این حالت ابجکت قبلی تغیر نمیکند ولی المنت جدید ایجاد می شود و می توانید با DOM searching مجددا به المنت جدید دسترسی پیدا کنیم یکی از تفاوت های دیگه این هست که inner محتوای داخل تگ هرچی باشه به ما میدهد ولی outer علاوه بر محتوا خود اون تگ رو هم میاد و به ما می دهد
تفاوت در نوشتن inner HTML += vs elem.i nner HTML = elem. inner HTML
inner HTML += محتوا را به طور کامل باز نویسی میکند یعنی ابتدا میاد و کل محتوای قبلی رو حذف میکند و سپس محتوای جدید را می نویسد و در نتیجه عمل ری رندر اتفاق می افتد و تمام منابع از جمله عکس ها مجددا بارگزاری می شوند
text Content : فقط محتوا رو به من بده بدون هیچ تگی و نوشتن محتوا با استفاده از آن امن تر است و محتوای متنی معمولی فقط به ما می دهد
ویژگی elem . hidden برای مخفی کردن المنت هامون هستش و دقیقا مثل این کاربرد دارد که display رو برابر none قرار دهیم
کار کردن با ویژگی ها یا Attribute ها : به طور کلی به دو دسته standard و non - standard تقسیم می شوند
standard ویژگی هایی هستند که روی هر المنت به صورت پیش فرض اومدن و تعریف شده اند و می توانیم با استفاده از پراپرتی های آبجکن های دام به اون ها دسترسی داشته باشیم non - standard برای دسترسی به این ها با استفاده از پراپرتی ها نمی توانیم بلکه برای دستری باید از توابع استفاده بکنیم
توابعی که برای کار با Attribute داریم نام Attribute به بزرگی و کوچکی حساس نیست و می توانیم با استفاده از توابع زیر به none - standard ها دسترسی پیدا کنیم
elem.hasAttribute( name ) ===> check for existence
elem.getAttribute( name ) ===> gets the value
elem.setAttribute( name,value ) ===> set the value
elem.removeAtribute( name ) ===> removes the attribute
نکته ای که وجود دارد در هنگام کار بار setAttribute ویژگی یا پراپرتی value کار نمیکنه متاسفانه و فقط باید از get استفاده بکنیم
برای استفاده از بعضی ویژگی ها که مقداری ندارند مثل check که فقط نوشته میشه ومقدارش با نوشتنش تغیر میکنه
console.log(input.check)
ایجاد Element و text Node :
document.createElement(tag) برای درست کردن المنت از دستور
document.createTextNode(text) برای درست کردن text Node
که در نهایت میایم و اون هارو به HTML امون اضافه میکنیم
برای جانمایی المنت ها ما مثل جی کوری 4 تا تابع مهم داریم که دو تای اول append و prepend که میاد و به انتها و ابتدای محتوای داخل المنت های داخل تگ امون اضافه میکنه و before و after میاد و به قبل و بعد تگ مورد نظرمون اضافه میکنه علاوه بر موارد بالا می تونیم بیایم و از تابع insert Adjacent HTML هم استفاده کنیم که مقدار اول میگوید به کجا اضافه کنم و مقدار دوم تابع ما یا المت اضافه کننده ما رو میخاد
ol .insertAdjacentHTML(* , html ) ;
* : beforbegin afterbegin appendbegin prependbegin
برای حذف المنت امون هم از تابع remove استفاده میکنیم برای کپی هم از تابع clone Node استفاده میکنیم که اگر مقدار true بهش بدیم محتوای داخل اش رو هم برامون کپی میکنه و اگر مقدار false بهش بدیم فقط خود تگ رو برامون کپی میکنه
Document Fragment : در واقع یک نوع آبجکت نود هستش که یک ویژگی خاصی رو دارد که قابل دیدن نیست و فقط برای مدیریت کردن دام ساختن و حذف آن استفاده میشود در دام های بزرگ در بحث پرفورمنس تاثیر زیادی دارد چون تا وقتی اون تغیراتمون تکمیل نشده اون صفحه دائما نمیاد و دوباره رندر بشه و دام امون هس دوباره رندر شه فقط اون تغیراتی که دادیم میاد و تغیر میکنه و رندر می شه
نکته : استفاده از فرگمنت ها این هستش که رندر کردن صفحه مارو کاهش میده و به این صورت پرفورمنس رو افزایش میدهد
کار کردن با کلاس ها و استایل ها در دام
mydiv.classList ==> return Array Class
mydiv.classList.add
mydiv.classList.remove
mydiv.classList.toggle
mydiv.classList.contains
mydiv.style
mydiv.computedStyle تمامی استایل هارو نشون میدهد و بهتر هستش
مختصات و اندازه المنت ها در صفحه :
content width : اون بخش از Box یا المنت ما که محتوا اون رو اشغال کرده
offset Left & offset Top : که مشخص میکند که اون باکس امون چقدر از بالا و چقدر از چپ صفحه ما فاصله داره
Client Top & client left : که در واقع میاد و حاشیه ها یا اون مقدار border width ما رو مشخص میکند
client width & client height : که در واقع میاد و مقدار های ارتفاع و عرض در فضاهای داخلی اون باکس ما رو مشخص میکند
offset Width & offset Height : که میاد و مقادیر عرض و ارتفاع رو همراه با اون border ها یا حاشیه ها به ما نشون می دهد
scroll Top : اون بخشی از اسکرول رو میاد و نشون میدهد که ما زدیم و یک بخشی از محتوامون رفته بالا
اسکرول :
alert('Curent scroll from the top:' + window.pageYOffset)
alert('Curent scroll from the left:' + window.pageXOffset)
توابع اسکرول در صورتی کار میکند که DOM کامل بارزگاری شده باشند و به همین دلیل اگر کد ها در تگ head باشند توابع اسکرول کار نمیکند
scroll To : کل صفحه در نظر میگیرد و برای کل صفحه اعمال می شود
scroll By : بر اساس پوزیشن فعلی ما میاد و حرکت میکنه و بر اساس اون موقعیت تغیر میکند
scroll into View : اگر مقدار درست بود میگوید برو و صفحه رو به شکلی بیار که اون المنت در بالای صفحه باشد و اگر نادرست باشد صفحه رو طوری اسکرول کنه که المنت من پایین صفحه باشد
ما برای پیدا کردن نقاط در DOM دو تا نسبت داریم یکی به نسبت window و دیگری به نسبت document که برای اولی باید client X و client Y رو پیدا کنیم و دومی هم باید page X و page Y باید محاسبه کنیم وقتی به نسبت داکیومنت هستش مثلا اگر بیاد و اسکرول بخوره دقیقا از اول اون سندمون که اسکرول خورده رو برای ما در نظر میگیرد ولی window میاد و متناسب با اون محتوا یا المنت امون که دیده میشه برای ما در نظر میگرد ما می توانیم با استفاده از مقایری که تابع get Bounding Client React میاد و به ما بر می گردوند اطلاعات مورد نیاز پیرامون صفحه ای که در اون قرار داریم رو به دست بیاریم
left = x top = y right = x + width bottom = y + height
ما در css وقتی میایم و میگیم right میاد و مختصات رو از سمت راست محاسبه میکنه ولی در جاوااسکریپت مبنای همه محاسبات از سمت چپ و بالا است ( مختصات گوشیه ی سمت راست رو به نسبت ویندو سمت چپ میاد و به ما میدهد )
تابع element From Point یک جور سلکتور هستش که میاد و مختصات رو از ما میگیرد و اون المنتی که در اون جا قرار داره رو برای ما بر میگردونه برای مثال
let centerX = document.documentElement.clientwidth / 2;
let centerY = document.documentElement.clientHeight / 2;
ket elem = document.elemntFromPoint(centerX,centerY);
elem.style.background = "red";
alert(elem.tagName);
مختصات به نسبت Document : که اگه اسکرولی اتفاق نیوفته باشه مقادیر باهم برابر هستش
pageY = clientY + اسکرول افقی
pageX = clientX + اسکرول عمودی
document.onmousemove = function(event){
event = event || window.event;
if(event.pageX == null && event.clientX !== null){
event.pageX = event.clientX + document.body.scrollLeft;
event.pageY = event.clientY+ document.body.scrollTop;
}
let hoveredElem = document.elementFromPoint(event.pageX,event.pageY)
if(hoveredElem.tagName != 'BODY'){
hoveredElem.style.backgroundColor = 'gray';
}
}
function leaved (event){
event = event || window.event;
event.target.style.background = '';
}
for(let elem of document.body.childNodes){
if(elem instanceof Elemnt){
elem.onmouseleave = leaved
}
}
مفاهیم JSON & AJAX : در اکثر api ها داده های خروجی به صورت JSON میاد وبر میگرده و چون قرار هستش با در خواتس های از نوع AJAX آشنا بشیم باید با جی سون هم آشنا شده باشیم
JSON : java Script Object Notation یا یک جور فرمت استاندارد متنی هستش
در تمام زبان های برنامه نویسی جی سون پشتیبانی میشود و ما میتونیم بیایم و خروجی تمام api هامون رو تحویل جاوااسکریپت بدیم و اون به راحتی ازون استفاده بکنه
نکته : دیتا تایپ جی سون از نوع string هستش و تعامل سرور با کلاینت به این صورت هستش که کلاینت ما میاد و یک http request به سمت سرور می فرسته و سرور هم یک پاسخ رو به صورت جی سون براش میفرسته
ما به طور کلی دو تا تابع اصلی برای کار با جی سون ها داریم
JSON.stringify() میاد و یک شی یا یک آرایه رو میگیره و تبدیل به جی سون میکنه
JSON.parse(text) یک جی سون رو میگیره واون رو تبدیل به یک آرایه یا آبجکت میکنه
مثال :
let test = { name : " Mehrdad "
family : " Dadkhak " }
console.log(test,JSON.stringfy(test));
let JSONA = test,JSON.stringfy(test)
console.log(test,JSON.parse (test));
AJAX مخفف کلمه ی Asynchronous JavaScript And XML هستش که از دو قسمت تشکیل شده است اولی از یکی از آبجکت های سند مرورگرمون به نام XML Http Request object و دومی هم java Script and HTML DOM
نکته : در حالت ajax مرورگر ما رفرش نمیشه
نکته : نوع درخواست get برای یک جور واکشی اطلاعات میاد و کاربرد داره همچنین درخواست از نوع post هم برای قرار دادن یک سری اطلاعات در داخل سایت درخواست pot هم برای ویرایش داده های موجود هستش و delete هم برای حذف کردن داده های موجود هستش
نکته : CORS Policy به یکسری درخواست قوانین میگن که سرور میاد و تعین میکنه که به ی سری خاص از ریکوست ها بیاد و پاسخ بده مثلا درخواست هایی که فقط از طریق دامین خودش ارسال شده است
معرفی سایت mocki.io که میاد و یکسری دیتا رو بریا تست به ما میدهد
متد on ready state change که چند تا وضعیت داره 0 درخواست هنوز آماده نشده 1 اتصال با سرور برقرار شده 2 درخواست دریافت شد 3 درحال پردازش درخواست 4 درخواست اتمام یافت و پاسخ آماده است
موتور V8 جاوا اسکریپ از دو کامپوننت اصلی تشکیل شده است اولی Memory Heap - جایی که اختصاص دادن حافظه صورت میگیره دومی Call Stack - این جا هم فریم های استک نگه داری میشه به هنگام اجرای برنامه
پشته اجرایی یا Call Stack : جاوا اسکریپت یه زبون تک تردی هست. به این معنی که فقط یه دونه پشته اجرایی داره. پس فقط در لحظه یه کارو میتونه انجام بده. پشته ی اجرایی یه ساختمون داده هست که از دستور هایی که باید اجرا بشن رو تو خودش نگه میداره عملا مشخص میکنه کجای اجرای برنامه هستیم. اگر وارد اجرای یه تابع بشیم اون تابع رو بالای این پشته گذاشتیم و هروقت هم در اون تابع ریترن کردیم از بالای پشته برش میداریم. این همه کاری هست که استک اجرایی میتونه انجام بده
نکته : هر ورودی به پشته اجرایی رو میگن Stack Frame.
نکته : منفجر کردن پشته اجرایی این زمانی اتفاق میوفته که به حد اکثر سایز پشته اجرایی برسیم. که خیلی هم ساده این اتفاق میتونه بیوفته اونم زمانی که داریم از تابع بازگشتی استفاده میکنیم و کدمون درست حسابی تست نکردیم. به این تیکه کد نگاه کنید:
function foo() {
foo();
}
foo();
وقتی موتور شروع به اجرای این کد میکنه از تابع foo کارشو استارت میزنه. این تابع بازگشتی هست و خودش رو صدا میزنه بدون هیچ شرط اتمامی. پس تو هر مرحله ی اجرا هی تابع foo به پشته اضافه میشه. و stack پر میشه و مرورگرمون در نهایت هشدار maxium call satck size exceeded
Web APIs : شامل توابعی مثل setTimeOut DOM BOM setInterval
events loops : ایونت لوپ فقط یه کار ساده داره. اونم مانیتور کردن call stack و callback queue. اینجوری کار میکنه که هر وقت call stack رو خالی ببینیه از صف کالبکها یه دونه برمیداره و به call stack اضافه میکنه و در جا اجراش میکنه. در event loop به هر بار تکرار این اتفاق یه tick گفته میشه و هر آیتم درون صف یک event نام داره که در حقیقت یه تابع callback هست.
تابع setTimeout چه جوری کار میکنه؟
نکتهی مهم در مورد setTimeout اینه که به صورت اتوماتیک تابع کالبک ما رو وارد صف event loop نمیکنه. یه تایمر درست میشه و هر وقت که تایمر منقضی بشه میزبان تابع کالبک ما رو تازه وارد صف میکنه و تابع باید صبر کنه تا فرآیند tick اتفاق بیافته تا از صف event loop به call stack منتقل بشه.
setTimeout(myCallback, 1000);
معنی کد بالا این نیست که my Callback دقیقاً بعد از ۱۰۰۰ میلیثانیه اجرا میشه. در حقیقت بعد از این مدت my Callback تازه به صف event loop اضافه میشه. و خب تازه آخر داستان نیست. اگر تو صف event loop توابع دیگه زودتر تو صف وارد شده باشن اجرای تابع my Callback بیشتر به تعویق میافته.
برای به دست آوردن اندازه Browser Window
برای به دست آوردن عرض
var w = window.innerWidth;
document.documentElement.clientWidth;
document.body.clientWidth;
برای به دست آوردن طول
var w = window.innerHeight;
document.documentElement.clientHeight;
document.body.clienHeight;
توابع کار با window
window.open()
window.close()
window.href()
window.moveTo()
window.resizeTo()
برای گرفتن اطلاعات صفحه کاربر
screen.width()
screen.height()
screen.availWidth()
screen.availHeght()
screen.colorDepth()
screen.pixlDepth()
برای گرفتن لوگشن صفحه از کاربر از اطلاعات زیر استفاده میکنیم
window.location.href()
window.location.hostname()
window.location.pathname()
window.location.protocol()
window.location.assign()
استفاده از صفحه پارالکس با استفاده از جاوااسکریپت که میاد و با استفاده از اسکرول در صفحه المان هامون رو بهمون نشون میدهد
برای درست کردن چنین چیزی ما باید از چندین گام بیایم و استفاده بکنیم برای همین
گام اول اوکی کردن تغیرات و انجام کد های html امون هستش
گام دوم برای اینکه بیایم و اسکرول هارو بفهمیم از دستورات زیر استفاده میکنیم
document.addEventListener('scroll',()=>{
// do something on scroll
console.log('We are scrolling');
}
گام سوم هم این هستش که بیایم و اجزای صفحه امون رو پیدا کنیم و به اون ها دسترسی داشته باشیم
const fg =document.querySelector('.foreground');
const mg =document.querySelector('.middlegroup');
const bg =document.querySelector('.background');
const title =document.querySelector('.firstpage h1');
const FIRST_PAGE_MAX_SCROLL = 500;
const FIRST_TRANS_MIN = 400;
const FIRST_TRANS_MAX = 600;
const SECONDPAGE_BR = 1100;
گام چهارم هم این هستش که وقتی اسکرول رو مدیریت میکنیم و اجزا را حرکت میدهیم که این کار رو باید با استفاده از تکنیک های css بیایم و انجامشون بدهیم
document.addEventListener("scroll", function (event) {
let scrollOffset = window.pageYOffset;
if (scrollOffset <= FIRST_PAGE_MAX_SCROLL) {
secondPage.style.opacity = 0;
firstPage.style.opacity = 1;
let p = scrollOffset / FIRST_PAGE_MAX_SCROLL;
mainTitle.style.transform = `scale(${1 + (0.1 + p)})`;
background.style.transform = `scale(${1 + (0.6 * p)})`;
foreground.style.transform = `scale(${1 + p})`;
middleground.style.transform = `scale(${1 + (0.4 * p)})`;
}
if (scrollOffset > FIRST_TRANS_MIN && scrollOffset <= FIRST_TRANS_MAX) {
let op = scrollOffset / FIRST_TRANS_MAX;
firstPage.style.opacity = 1 - op;
secondPage.style.opacity = op;
} else if (scrollOffset > FIRST_TRANS_MAX && scrollOffset <= SECONDPAGE_BR) {
let yChanger = scrollOffset - FIRST_TRANS_MAX;
spans[0].style.transform = `translate3d(0, ${yChanger}px,0)`;
spans[2].style.transform = `translate3d(0, -${yChanger}px,0)`;
} else {
let thirdScroll = scrollOffset - SECONDPAGE_BR;
thirdPage.style.opacity = 1;
app.style.transform = `translate3d(0, -${thirdScroll}px,0)`;
}
});
سلام و عرض ادب جناب دادخواه
این دوره تموم شده قسمت هاش؟ آخه در توضیحات دوره فرمودین که این مفاهیم هم آموزش داده میشن : (مباحثی مانند توابع سازنده، شی گرایی و مباحثی مانند Prototype و ارث بری در جاوااسکریپت و هم چنین Events در این دوره بررسی خواهد شد. )