簡單來說在一個帶有參數 a 的函式中返回另一個使用到參數 a 的函式
此時在函式外可以獲取到參數 a 就稱為閉包
即把參數存到一個新的函數中 保留其記憶體位置 就是閉包
function makeAdder(x) {
return function(y) {
// 函數被 return 後,還是能繼續存取環境中的 x 變數
return x + y;
};
}
// 建立一個新變數指向原本的函數 傳入 x 值,調用後可以得到 x 就是一個閉包
var add5 = makeAdder(5);
console.log(add5(2)) // 所以這裡結果為 7
上述可以發現 add5 本身只有傳入 y 值
但還是可以獲取到 makeAdder 的 x 值
這就是所謂的閉包了 在記憶體中保留了 x 的位置 使其可以繼續被抓取使用
在宣告變數前先引用變數 不會出現 xxx is not defined 報錯,而是出現 JS 中的預設值 undefined ,就是所謂的提升。
函數與 var 宣告的變數都會被提升,且函數被提升的權重會高於變數。
參考文章 - 這篇我大概也只看懂一半
先上一段有趣的小東西:
console.log(undefined == null)
console.log(undefined === null)
上方代碼輸出結果第一行會為真,第二行則為假
原因是這兩者都屬於 falsey 但是兩者的型別是不同的
在 JS 中 null 屬於 object 型別
而 undefined 的型別則還是 undefined
這也導致在第一行程式碼判斷中 falsey = falsey 所以是 true
然後第二行程式碼會判斷兩者型別 發現 object != undefined 所以返回 false
有趣吧?也附上一篇短短的參考文章
call 與 apply 都會把傳入的第一個參數定義為 this 的指向
其他參數則依序作為原本的參數傳入函數裡
兩者的差別是 apply 傳入的其餘參數必需要用陣列方式傳入
參考文章
session 被存在伺服器端,cookie 被存在客戶端
上述兩者在瀏覽器關閉時都會失效,
session 的安全性 > cookie 的安全性。
localstorage 被存在本地端,
除非被手動刪除,否則會永久保存在本地端。
每個執行環境都有一個參照的外部環境
這個外部環境會看你當前執行的程式碼處於哪種詞彙環境
即他看的是你在聲明時存在的位置所決定的,而不是執行或調用的位置外
所以下方程式碼:
function b (){
console.log(x);
}
function a (){
var x = 2;
b();
}
var x = 1;
a();
在函數 b 的外部參考會是全域中的 x 而不是執行它的函數 a
所以輸出的 x 會是全域中的 1 ,這就是詞彙環境(看該程式碼實際上在物理上存在的位置決定)。
參考文章
要先知道,在 JS 中每個物件都有自己的原型(.prototype
),
而物件的原型還會有其原型(.__proro__
),
直到該原型的原型(.__proro__
)輸出為 null 為止。
這過程就稱為一個原型鏈。
原型主要用於建構函數中的方法。
當創建建構函數後,
在 new 出來的物件中就可以調用到建構函數中的方法與其原型中的方法,
我們可以通過原型去給建構函數建立方法,
而不需要在每個 new 出來的物件中重複創建新的方法,
通過原型建立的方法可以讓所有 new 出來的物件都使用到,
假設你在每個 new 出來的物件中撰寫方法,
會導致佔用非常多記憶體位置,
但如果你是使用原型方式建立方法,
就只需要佔用一個記憶體位置了。
參考文章 - 內附程式碼說明,較清楚
雙等於:先轉換型別後比較,其值若相等則返回 true
全等於(三等於):嚴格比較,不會轉換型別,一開始先判斷型別,若不相等會直接返回 false
幾個要注意的判斷:
可以簡單理解為物件與函數是傳參考 其他變數字串陣列等都是傳值
傳值表示每個東西都是獨立存在 只是把值複製一份給其他東西使用
傳參考則表示每個東西所指向的是同一個記憶體位置 修改其值就會導致共享該記憶體的其他東西一起被修改
參考文章
class 物件導向設計,
箭頭函數,
函數參數預設值,
export&import,
模板字串(使用反引號拼接字串),
解構賦值,
promise,
let&const,
Symbol,
…展開/其餘運算符。
參考文章 - 還有很多其他技術
首先我們知道 JS 是屬於同步的程式語言,當遇到非同步事件時,他會先執行所有的同步事件,等所有同步事件處理完畢後才會執行那些非同步事件, JS 的非同步事件有計時器或 AJAX 事件等,假設需要在確保非同步事件完成後才繼續執行其他程式碼,就需要使用 promise 了。promise 的強大特性是他可以通過鏈接(.then().catch())執行下一個動作,而不需要使用回調地獄。
參考文章
可以簡單理解為等號右方的資料會對應到左方同位置的資料。
細節部分比較繁雜可以直接閱讀參考文章。
參考文章
var 的作用域是全域
let 的作用域是 block 即每個 {} 中獨立存在
const 是常數 聲明後即不能被修改 且在聲明時若沒有賦值會報錯
參考文章
除了他可以有效的簡化寫法外,其 this 是完全綁定在語彙上的位置,也就是說在箭頭函數裡的 this 永遠都是語意上的 this ,不管是誰呼叫他,或是被如何 bind 、 call 、 apply ,他永遠都是拿到原先作用域的 this 。
這樣的做法可以讓你在物件上使用回調時,拿到正確的 this ,而非一言不合就 undefined
參考文章 - 箭頭函式與傳統函式之差異
在大型專案或專案結構較複雜時段於管理資料會方便很多
如兩個兄弟組件之間的溝通 在沒有使用 Vuex 的情況下會變得很麻煩
但使用 Vuex 就可以統一管理資料結構了
可以,只需要在 style 標籤加上 scoped 屬性
即可把樣式限制在該元件中做使用
GET: 讀取(獲取)資源
PUT: 更新資源
DELETE: 刪除資源
POST: 創建資源
PATCH: 更新部分資源
他的中文翻作伺服器渲染,執行過程如下:
輸入網址 => 發送請求 => 接收響應(響應回來的直接是一個頁面) => 瀏覽器解析渲染畫面
另外有一個 CSR 中文翻作客戶端渲染,執行過程如下:
輸入網址 => 發送請求 => 接收響應(響應回來的是一個模板頁面 需通過 js 解析後才能渲染) => 在響應回來的模板中透過 js 逐行解析,當遇到 ajax 時再發送新的請求 => 最後渲染畫面
參考文章 - 這篇跪著讀
瀏覽器輸入網址後會先查找 IP 地址,
接著通過 TCP 三次握手確認雙方已建立好連結,
然後瀏覽器就可以針對 IP 地址發送請求並等待響應,
此時響應會被拆成很多個封包,最後封包合併後傳送 200 ok
表示響應接收成功,瀏覽器再解析響應數據並渲染畫面,
最後會進行四次揮手道別中斷雙方連結。
參考文章 - 這篇也很強大繼續跪著看
https 在應用層與傳輸層之間多了一道 SSL 加密憑證
這個 SSL 可以防止在發送 HTTP 的 GET 或 POST 請求的時候被攔截獲取到資訊
在客戶端向伺服器發送請求時不需等待響應,可以繼續執行其他動作,且接收到響應後不會刷新整個頁面,而是利用 JS 與 DOM 進行局部內容替換,這就是所謂的 AJAX 非同步。
最原生的實現方式是使用 XMLHttpRequest 物件 但因為寫法過於繁雜
後來 jQuery 又推出了 $.ajax()
方法
接著是結合 ES6 promise 的 fetch()
方法
最後出現了依賴於 ES6 promise 的 axios 輕量級套件
參考文章
沒有包含文字大小。
盒模型指的是:寬度、高度、邊框、內距與外距這五者。
有設置 position(非預設值 static)的元素才能使用 z-index 屬性
且 z-index 的值須為整數
幾乎都會使用到,可以方便的計算元素大小,省去很多煩雜的計算。
他讓尺寸不再只是寬度與高度,而是寬度與高度外,又包含了 padding & border
參考文章
HTML tag 1分
class 10分
id 100分
行內 style 1000分
!imporant 10000分
參考文章
大型專案上較常使用 SCSS 撰寫
使用語意化方式命名 多數使用小駝峰命名法
了解 OOCSS 的結構與樣式分離、容器與內容分離概念
了解 BEM SMACSS 等概念
參考文章 - CSS 模組化有哪些方法
通常 id 都是跟 js 配合或作為錨點用的
且在 CSS 上會盡量避免使用 id ,因為兩者權重差很多
另外就是相同 class 可以有多個,但相同 id 只可以有一個
參考文章
ps 文章參考就好,親測 id 可以用數字,只是在樣式中用#數字會報錯,但JS不會出錯
我個人通常是有使用 Bootstrap 就會用 但基本上會看設計稿需求
平常手刻不會刻意製作 但不排斥 也有嘗試手寫過格線系統
參考文章 - 格線佈局的概念
使用 Sass 編譯 + CSS Reset
參考文章 - 我其實沒研究過這問題
none、inline、inline-block、block、inline-flex、flex、table、inline-grid、grid、unset
參考文章 - 其他我不知道,但還有好多
Normalize 保留一些常用的預設樣式 如列表 標題等
Reset 把所有瀏覽器預設樣式都清空了
參考文章
PNG:有效減少圖片檔案大小以及保留照片透明元素,圓角圖片就很適合使用。
SVG:向量檔,縮放不失真,用在 logo 很方便。
GIF:可以製作小型動態圖片檔案,適用於色彩簡單的檔案,也有支援透明背景。
參考文章
rem 是指 root 層級的文字大小,即 html 標籤的大小,通常是 16px ,可以通過設定 html 的 font-size 影響到所有使用 rem 單位的尺寸。
參考文章
用於強制性覆蓋樣式,因為 important 的權重在 CSS 中是最高的,可以通過這種方式強制把想要的樣式覆蓋上去。
/* 設在子元素,內容只有一行文字時才適用 */
.method1 {
margin: auto;
line-height: 父層高度;
}
/* 設在父元素 */
.method2 {
display: flex;
justify-content: center;
align-items: center;
}
/* 設在子元素 */
.method3 {
position: absolute; /*父層需加上 position: relative; */
transform: translate(-50%, -50%);
top: 50%;
left: 50%;
}
/* 設在父元素 */
.method4{
display: flex; /* 子元素設置 margin: auto; */
}
題目要求:
可以新增項目
完成的項目會有刪除線
可以刪除單個項目
網頁重整也能夠保存資料(使用 cookie or localstorage)
const data = JSON.parse(localStorage.getItem("datas")) || [];
oInput.addEventListener("keyup", function (e) {
if (e.keyCode == 13) {
let obj = {};
obj.content = oInput.value;
obj.checked = false;
data.push(obj);
oInput.value = "";
init();
}
});
oUl.addEventListener("click", function (e) {
let i = e.target.getAttribute("data-num");
if (e.target.nodeName == "A" && e.target.getAttribute("class") == "delete") {
e.preventDefault();
data.splice(i, 1);
} else {
data[i].checked = !data[i].checked;
}
init();
});
function init() {
let str = "";
data.forEach(function (item, i) {
if (item.checked) {
str += `<li data-num=${i}><del>${item.content}</del><a class="delete" href="#" data-num=${i}>刪除</a></li>`;
} else {
str += `<li data-num=${i}>${item.content}<a class="delete" href="#" data-num=${i}>刪除</a></li>`;
}
});
oUl.innerHTML = str;
localStorage.setItem("datas", JSON.stringify(data));
}
init();
function test() {
for (var i = 1; i < 10; i++) {
for (var j = 1; j < 10; j++) {
console.log(`${i} * ${j} = ${i * j}`);
}
}
}
test();
// XML 最基礎的原生方法
var req = new XMLHttpRequest();
req.open("GET", '網址');
req.send();
req.onreadystatechange = function () {
if (this.readyState == 4 && this.status == 200) {
var data = JSON.parse(req.responseText);
for (i = 0; i < 10; i++) {
console.log(data[i].name);
}
}
};
// ES6 的 fetch 方法
fetch('網址')
.then(res => {
return res.json();
})
.then(result => {
result.data.forEach((item, i) => {
if(i < 10) {
console.log(item.name);
}
})
});
// 引用 axios 方法
axios.get('網址')
.then((res) => {
res.data.forEach((item, i) => {
if(i < 10) {
console.log(item.name);
}
})
});