web
frontend
JS 的基本型別(Primitives)有 String(文字)、 Number(數字)、 Boolean(true/false)、 undefined、 null
JS 中變數為寬鬆型別,不用事先宣告型別(type)
區分大小寫、不可用保留字、不可用數字開頭
在宣告變數的同時也可以給定初始值,給值的同時也決定了變數的型別(type)
block
就是區塊,是程式中的一塊獨立段落。 C 式語系中,由 {
}
包起的內容就屬於一個 block
(區塊),而在區塊之中還可以有小區塊。層層區塊組成巢狀結構。scope
的變數活動範圍、或稱作用域的觀念。在 main 區塊中,又寫了一對 {
}
劃出一個小區塊,亦即一個新的活動範圍。所以我可以在這個小區塊中再宣告一次 i 。
符號 i 在這一大一小兩區塊中,分別繫結兩個不同活動範圍的變數。所以小區塊中令 i 為 1 的敘述,並不會影響到大區塊的 i 值。一前一後的兩行輸出指令,也就分別輸出 1 和 0 兩個結果。
如果你把這個 C 語言範例中的第5行和第8行的角括號拿掉的話,編譯器會直接告訴你重複宣告變數。
但是同樣的想法,用在 JavaScript 就錯了。先看看下面的 JavaScript 範例:
前後兩行都顯示 1 ,也就是在小區塊中第二次宣告 i 並賦值為 1 的敘述,其實作用在第一次宣告的 i 身上。
這表示在 JavaScript 中,區塊並不等於活動範圍。一大一小兩區塊的 i 都繫結到同一個變數了。
在 ES6 之前的規範中,對於 scope
的定義只有兩種
你每定義一個函數,就會建立一個屬於這個函數的活動範圍;不在函數內的資源就屬於全域活動範圍。
因為沒有採用區塊即活動範圍的定義。所以像 C 語言那樣的區塊用法,在 JavaScript 中就是錯的。
ES6 以前,也只有 var 一種變數宣告方式。它的用途和函數活動範圍有關。
var 是看函數,而不是區塊。
let 和 var 不同之處在於它帶來了以區塊為活動範圍的定義。
在 ES6 中,你可以在 for 區塊、if 區塊、或者是不帶任何控制目的純區塊中,使用 let 宣告以區塊為活動範圍的變數。
因此若將前述JavaScript 的範例程式碼中以 var 宣告的變數全改為以 let 宣告,就會跑出正確的結果。
let 是看區塊,而不是函數。
凡是用 const 定義的符號,其繫結的內容僅能在定義時設定初值,之後不允許再改變,這就是常數了。
試圖改變 const 常數的敘述,都是語法錯誤。除此之外,const 的語法限制和 let 相同,不允許重複宣告、不允許宣告前使用。
const是看區塊,而不是函數
const 常數還有一點要注意,它可以在定義時計算初值。
所以定義時的初值部份不限定為字面內容,而可以使用變數或函數等運算敘述。
若初值部份用了變數或運算敘述, JavaScript 會將計算結果作為初值。
即使你之後改變了那個變數,也不會影響 const 常數的內容。
若以 const 宣告物件或陣列,還是有辦法更改裡面的值,
像是
要解決這個問題可以用
輸出x的m次方
產生min~max間的隨機亂數
new Date (year, month, date, hours, minutes, seconds, ms)
統一資源標識符(Uniform Resource Identifier,或URI)
是一個用於標識某一網際網路資源名稱的字元串,
而URL (定義位置) 和 URN (定義身份) 則是URI的子集。
在處理網頁(址)資料,常會有遇到中文字或是空白、標點符號等問題(英文、數字通常不會有問題),
此時就可以使用 URI 編碼函數(通常標點轉為十六進位ASCII、中文轉成十六進位統一字元碼),
如需轉回則使用解碼函數。
encodeURIComponent()不編碼符號包括: ~ ! * ( ) '
適合參數編碼,應用範圍廣
三者皆會在瀏覽器顯示對話框 但用處各自不同
其中 confirm('text') 和 alert('text') 類似
都會把參數內的字串顯示在對話視窗中
但confirm()有確定和取消 會回傳 true
或 false
prompt()則是除了顯示文字外 還可以讓使用者輸入數值
迴圈可以用 break、continue 來中斷迴圈 ; 而函數的 return 除了用來回傳值,也可用來中斷函數。
作法為 return 一個 value 或是乾脆回傳空值
if
else
可以簡寫
一般而言 JavaScript 有 內建函數 和 自定義函數
在 JS 中 函數在被執行之前會被解析(hoisted)
因此它可以在任意的地方都是有宣告的 即便比這個函式還早呼叫
JavaScript 是 function scope
無論你在函數內哪裡宣告變數 var 都會提升到最前面宣告
稱為變數的拉升(Variable Hoisting),
建議把變數的宣告放在函數的最頂端 否則可能導致混亂的情況。
但是使用 let 或 const 須注意,並不會自動拉升,所以在宣告前使用的話會顯示 is not define。
上面代碼實際執行狀況是
更精確的說 在我們定義變數的過程中
可以分成宣告(declaration)和給值(initialization)的兩個過程
只有declaration的內容會在逐行執行程式前先被執行並儲存在記憶體(hoisted)
給值的內容則是在hoisted後 逐行執行程式時 才會被執行到
所以程式一開始執行的時候 就已經把var a的宣告存在記憶體中了
但是還沒把值指定進去a這個變數當中 這使得a得到了undefined的結果
用 var 所宣告的變數 作用範圍是在當時所在環境(函數內)
而不使用 var 直接指定值而建立的變數 則是全域物件(window)上的一個屬性
也就全域範圍
在 JS 中有稱作 scope chain(範圍鏈)的特性
JS在查找變數時 會循著範圍鏈(Scope Chain)一層一層往外找
若函數內找不到 則往外找
注意:內層函式都可以存取外部函式的變數;但外部不能存取內部
自調用函數(立即函數)是一種
不用額外呼叫可自己立刻執行
方便建構自己的生存域
閉包(Closure)是擁有閒置變數(Free variable)的物件
建立函數不等於建立閉包
如果函數的閒置變數與當時語彙環境綁定
該函數才稱為閉包
閒置變數是指對於函式而言,既非區域變數也非參數的變數
上面doSome的例子中,f建立了一個閉包,如果你單看:
看來起x似乎沒有定義。實際上,x是從外部函式捕捉而來。
閉包是個捕捉了外部函式變數(或使之繼續存活)的函式。
在上例中,函式f建立了閉包,因為它將變數x關入(close)自己的範圍。
如果形式閉包的函式物件持續存活,被關閉的變數x也會繼續存活。
就像是延續了變數x的生命週期。
由於doSome傳回了函式物件並指定給foo,就doSome而言已經執行完畢。
單看x的話,理應x已結束其生命週期,但由於doSome中建立了閉包並傳回,x被關閉在閉包中,所以x的生命週期就與閉包的生命週期相同了。
如上例所示,呼叫foo(20)結果就是10+20(因為被關閉的x值是10),呼叫foo(30)結果就是10+30。
注意!閉包關閉的是變數,而不是變數所參考的值。
建立閉包時,綁定了x變數,而不是數值10(x變數的值),
也因此doOther之後改變了x變數的值,而後傳回閉包給foo參數後,
範例顯示的結果分別是100+20與100+30。
你可能會有疑問的是,如果閉包關閉了某個變數,使得該變數的生命週期得以延長,那麼這個會怎麼樣?
像這類的例子,其實結果是很一致的,關閉的是建立閉包時外部範圍下的變數。
以上例來說,第一次呼叫doOther時,建立了x變數,指定值給x變數,而後建立閉包將之關閉。
第二次呼叫doOther時,建立了x變數,指定值給x變數,而後建立閉包將之關閉。
所以f1與f2關閉的根本是不同作用範圍的x變數(也就是該次呼叫doOther時所建立的x變數)。
所以上例中,呼叫f2之後顯示的值仍是9
下面這個也是個例子
使用閉包來定義公共函數,且其可以訪問私有函數和變數。
這個方式也稱為模組模式(module pattern)
上方全部都顯示 5 是因為 JS 在執行 for 時,會把 setTimeout 放進 Queue 中,所以迴圈跑完才會執行 setTimeout ,但此時的 i 是全域變數,也就是跑完迴圈後的 i = 5,所以 console.log(i) 才會顯示 5。
關於 JS 中 Stack、Queue、WebApis 更詳細的說明
可以使用閉包解決這個問題,讓 i 的值與當時的環境綁定:
其實 ES6 之後有更簡單的方法解決這個問題:
改成 let 即可,這也像閉包的概念,因為迴圈執行完後,i 並不是全域變數,所以會綁定當時生成的環境。
可以寫成
與 forEach 相似,但會有回傳值
可是 map 不適合拿來過濾
回傳所有結果為 true 的值
結合 map
與 filter 原理相同,但差別在 find 只會回傳第一個為 true 的結果。
檢查所有判斷結果,全為 true 則 return true,有一個 false 則 return false。
檢查所有判斷結果,只要有一個 true 則 return true。
一樣對陣列進行遍歷操作,但會將每回合 return 的值,傳入下一回合,所以可以用來加總。
兩者結合
依序 return 陣列每個值
故可以使用此種寫法改寫上方的陣列合併
和物件一樣,Array 也是傳參考,如果想要實現陣列的深拷貝,可以使用 ES6 延展快速實現,因為它和手動取值一樣,依序取出陣列的值。
結構與陣列幾乎一樣,但是能夠使用 __proto__
中的函數較少。
正常 Array
套用延展特性,可以使類陣列轉為正常陣列
JS 函數中,若傳入未定義的參數,實際上還是會透過 arguments
變數存起來(有定義的參數也會存進)。
而聰明的你一定會想到,沒錯,這個 arguments 也是類陣列,沒有辦法使用太多的方法,像是加總(reduce),那解決方法也是透過上方的延展來轉換。
此處介紹的其餘參數和上方 arguments
概念類似,但 arguments
是將所有傳入函數的參數存起來,不論那些參數有沒有定義,而其餘參數則是存放沒有定義的參數而已。
此範例結果乍看之下和 arguments
差不多,
但是改成這樣,就發現 Bob 是傳入有定義的參數 name,而其餘未定義的參數則被放入 money 中。
這樣的場景有沒有似曾相似…
現在不用再這麼麻煩了,而且左邊變數數量小於等於右數陣列長度就好。
如果想要跳過某一個值,可以改成這樣
蛤,上面的場景你沒見過?
那這個呢…
一樣,可以直接改成簡潔有力的寫法
左邊搜尋文字可以放正則式,常用寫法為 /搜尋文字/g
可以到陣列>解構賦值看更多說明
也可以這樣寫,當一筆資料有 key 時,不想用陣列儲存,可以用這種方式:
除了基本型別(Number、String、Boolean、null、undefined)是 call by value 之外,
Array、Object 為 call by reference(sharing)。
那該怎麼單純的取物件的值呢?
同樣的範例還有
但是沒這麼簡單,以上方法只能深拷貝一層,也就是可能會發生以下狀況
注意到了嗎
b 改變 name 並不會影響 a 的 name,但是改變再深一層的物件的值,就會影響到原本 a 的 language.chinese 了!
當初遇到這個問題爬了一下文,才知道原來這是很熱門的問題,也是面試常常會被問到的XD
那該怎麼解決呢?
如果想要將取出的值放到不同名稱的變數上
若屬性與值的名稱一樣,則可省略後者
函數也可以縮寫
in
取 key
of
取 value
如果是陣列的話,也可以用 forEach 個別操作元素
這邊有一個方法可以快速判斷某 id、class 之元素是否存在
innerHTML使用上需注意資料來源是否安全
這是一個簡易的留言板,會把用戶輸入的內容顯示出來
但是如果前後端沒有過濾掉一些非法字元,導致內容直接傳入資料庫,會發生安全問題。
Ex用戶輸入:
Hello會正常顯示,script不會顯示出來,但是已經被植入到頁面。這筆留言被傳入資料庫後,日後其他用戶到這個頁面時就會執行這段script
遇到屬性有 -
號的,移除後把後面的字母變大寫。
取得屬性值時會包含單位,ex: px、em…等等,若是要運算時需要轉為數字
setAttribute
getAttribute
但是元素無法一次綁兩個一樣的事件。
當事件觸發時,會自動把事件的詳細資訊傳入function中的第一個參數,通常會命名為e
或event
addEventListener的第三個參數決定事件處理是Event Bubbling(事件氣泡)還是Event Capturing(事件捕捉),一個是由內找到外(false預設);一個是由外到內(true)
舉例:
點click me時,console會先印出li
,再印出ul
。
但是改成true時,則會先印出ul
,再印出li
上一個例子,點click me時,會先顯示li
,再往外顯示ul
。
很多情況會遇到這種元素重疊的問題,當我們只想顯示點擊的li
時,可以把冒泡中止,不讓它再往外找。
有些元素會有默認行為,像是a連結點它會自動跳轉、submit點擊會自動把表單內容送出。
當我們不想讓它的預設動作執行時,可以取消它,像是前端想先檢查表單內容是否正確再傳到後端,所以要阻止submit點擊後就把內容送出。
若是想顯示點擊的li
內容,可以綁定每個li
再顯示
但是這樣需要個別綁定,效率較低,而且動態新增的元素不會被綁定。
較好的做法是綁定li
的父元素來監聽
screen 計算在整個螢幕之位置(算入解析度)
page 計算在瀏覽器中的網頁頁面之位置
client 計算在瀏覽器中的位置
知道滑鼠座標也可以把滑鼠圖示改變(覆蓋)成自訂圖案
若要更改用戶複製內容可寫
說明:
輸入重要資料時,不希望使用者使用複製貼上的方式可寫
瀏覽器儲存在本地端的資料,格式為Key : value
。
value 的型態只有 String
範例
全部移除
由於 value 只能存入 String ,所以要使用某些函數來轉換 String ,好方便存取。
可以存放 value 到 html 屬性中,格式為data-key="value"
存取方法為.dataset.key
動態新增 array 資料到 ul ,並紀錄 index 到 data-num 中,
點擊 li 時依所點之 num 來刪除 array 中相對應之 index。
相似於 localStorage ,不同之處在於 sessionStorage 在瀏覽器關掉後就自動清除。
開啟瀏覽器後會開啟 window
物件,裡面包含了很多資訊,像是 document 中的變數、函式。
列印
開啟視窗
網頁頁面寬高
瀏覽器寬高
配合 JS 動態指定圖片大小
回到上一頁
下一頁
顯示當前網址
跳轉到指定網址
顯示參數
ex: ?a=3&b=4
顯示瀏覽器資訊
顯示用戶當前是否連接網路
AJAX即「Asynchronous JavaScript and XML」(非同步的JavaScript與XML技術),指的是一套綜合了多項技術的瀏覽器端網頁開發技術。 來源:維基百科