摘要:記錄一些前端常用的基礎(chǔ)知識(shí)點(diǎn)地址,多多技能樹定義直譯為塊級(jí)格式化上下文。事件循環(huán)事件循環(huán)是指主線程重復(fù)從消息隊(duì)列中取消息執(zhí)行的過程。而且主線程只有在將當(dāng)前的消息執(zhí)行完成后,才會(huì)去取下一個(gè)消息。消息就是注冊(cè)異步任務(wù)時(shí)添加的回調(diào)函數(shù)。
記錄一些前端常用的基礎(chǔ)知識(shí)點(diǎn)
Github地址,多多star ^_^
技能樹 BFCBFC 定義: BFC(Block formatting context)直譯為"塊級(jí)格式化上下文"。它是一個(gè)獨(dú)立的渲染區(qū)域,只有Block-level box參與, 它規(guī)定了內(nèi)部的Block-level Box如何布局,并且與這個(gè)區(qū)域外部毫不相干。
BFC布局規(guī)則:
內(nèi)部的Box會(huì)在垂直方向,一個(gè)接一個(gè)地放置。
Box垂直方向的距離由margin決定。屬于同一個(gè)BFC的兩個(gè)相鄰Box的margin會(huì)發(fā)生重疊
每個(gè)元素的margin box的左邊, 與包含塊border box的左邊相接觸(對(duì)于從左往右的格式化,否則相反)。即使存在浮動(dòng)也是如此。
BFC的區(qū)域不會(huì)與float box重疊。
BFC就是頁面上的一個(gè)隔離的獨(dú)立容器,容器里面的子元素不會(huì)影響到外面的元素。反之也如此。
計(jì)算BFC的高度時(shí),浮動(dòng)元素也參與計(jì)算
哪些元素會(huì)生成BFC:
根元素
float屬性不為none
position為absolute或fixed
display為inline-block, table-cell, table-caption, flex, inline-flex
overflow不為visible
參考
瀏覽器渲染頁面過程用戶輸入U(xiǎn)RL地址
對(duì)URL地址進(jìn)行DNS域名解析
建立TCP連接(三次握手)
瀏覽器發(fā)送HTTP請(qǐng)求報(bào)文
服務(wù)器返回HTTP響應(yīng)報(bào)文
關(guān)閉TCP連接(四次揮手)
瀏覽器解析文檔資源并渲染頁面
TCP TCP三次握手 TCP四次揮手 JS單線程運(yùn)行機(jī)制消息隊(duì)列:消息隊(duì)列是一個(gè)先進(jìn)先出的隊(duì)列,它里面存放著各種消息。
事件循環(huán):事件循環(huán)是指主線程重復(fù)從消息隊(duì)列中取消息、執(zhí)行的過程。
主線程只會(huì)做一件事情,就是從消息隊(duì)列里面取消息、執(zhí)行消息,再取消息、再執(zhí)行。當(dāng)消息隊(duì)列為空時(shí),就會(huì)等待直到消息隊(duì)列變成非空。而且主線程只有在將當(dāng)前的消息執(zhí)行完成后,才會(huì)去取下一個(gè)消息。這種機(jī)制就叫做事件循環(huán)機(jī)制,取一個(gè)消息并執(zhí)行的過程叫做一次循環(huán)。消息就是注冊(cè)異步任務(wù)時(shí)添加的回調(diào)函數(shù)。
事件循環(huán)macroTask(宏任務(wù)): 主代碼塊, setTimeout, setInterval, setImmediate, requestAnimationFrame, I/O, UI rendering
microTask(微任務(wù)): process.nextTick, Promise, Object.observe, MutationObserver
事件 事件流事件捕獲階段
處于目標(biāo)階段
事件冒泡階段
事件委托不在事件的發(fā)生地(直接dom)上設(shè)置監(jiān)聽函數(shù),而是在其父元素上設(shè)置監(jiān)聽函數(shù),通過事件冒泡,父元素可以監(jiān)聽到子元素上事件的觸發(fā),通過判斷事件發(fā)生元素DOM的類型,來做出不同的響應(yīng)。
舉例:最經(jīng)典的就是ul和li標(biāo)簽的事件監(jiān)聽
HTML 基礎(chǔ)標(biāo)簽優(yōu)先級(jí): 行內(nèi)樣式 > 鏈接式 > 內(nèi)嵌式 > @import 導(dǎo)入式
選擇器/* 選擇所有元素 */ * { } /* 選擇 div 元素 */ div { } /* 選擇類名元素 */ .class { } /* 選擇 id 元素 */ #id { } /* 選擇 div 元素內(nèi)的所有 p 元素 */ div p { } /* 選擇 div 元素內(nèi)下一層級(jí)的 p 元素 */ div > p { }
css選擇器權(quán)重: !important -> 行內(nèi)樣式 -> #id -> .class -> 元素和偽元素 -> * -> 繼承 -> 默認(rèn)
文本溢出// 文本溢出單行顯示 .single { overflow: hidden; text-overflow:ellipsis; white-space: nowrap; } // 文本溢出多行顯示 .multiple { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 3; overflow: hidden; }CSS3 新特性
transition:過渡
transform:旋轉(zhuǎn)、縮放、移動(dòng)或者傾斜
animation:動(dòng)畫
gradient:漸變
shadow:陰影
border-radius:圓角
Javascript 原型與原型鏈實(shí)例的 proto 屬性(原型)等于其構(gòu)造函數(shù)的 prototype 屬性。
Object.proto === Function.prototype
Function.prototype.proto === Object.prototype
Object.prototype.proto === null
繼承實(shí)現(xiàn)function extend(child, parent) { var F = function() {}; // 空函數(shù)為中介,減少實(shí)例時(shí)占用的內(nèi)存 F.prototype = parent.prototype; // f繼承parent原型 child.prototype = new F(); // 實(shí)例化f,child繼承,child、parent原型互不影響 child.prototype.constructor = child; // child構(gòu)造函數(shù)指會(huì)自身,保證繼承統(tǒng)一 child.super = parent.prototype; // 新增屬性指向父類,保證子類繼承完備 }深拷貝
function deepCopy(s, t) { t = t || (Object.prototype.toString.call(t) === "[object Array]" ? [] : {}); for (var i in s) { if (typeof s[i] === "object") { t[i] = deepCopy(s[i], t[i]); } else { t[i] = s[i]; } } return t; }Ajax
var ajax = {}; ajax.get = function(url, fn) { var xhr = new XMLHttpRequest(); xhr.open("GET", url, true); xhr.onreadystatechange = function() { if ( xhr.readyState === 4 && (xhr.status === 200 || xhr.status === 403) ) { fn.call(this, xhr.responseText); } }; xhr.send(); }; ajax.post = function(url, data, fn) { var xhr = new XMLHttpRequest(); xhr.open("POST", url, true); xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); xhr.onreadystatechange = function() { if ( xhr.readyState === 4 && (xhr.status === 200 || xhr.status === 403) ) { fn.call(this, xhr.responseText); } }; xhr.send(data); };格式化日期
function formatDate(date, format) { if (arguments.length === 0) return null; format = format || "{y}-{m}-2a2k22s {h}:{i}:{s}"; if (typeof date !== "object") { if ((date + "").length === 10) date = parseInt(date) * 1000; date = new Date(date); } const dateObj = { y: date.getFullYear(), m: date.getMonth() + 1, d: date.getDate(), h: date.getHours(), i: date.getMinutes(), s: date.getSeconds(), a: date.getDay() }; const dayArr = ["一", "二", "三", "四", "五", "六", "日"]; const str = format.replace(/{(y|m|d|h|i|s|a)+}/g, (match, key) => { let value = dateObj[key]; if (key === "a") return dayArr[value - 1]; if (value < 10) { value = "0" + value; } return value || 0; }); return str; }new 實(shí)現(xiàn)
function New(Class) { let obj = {}; obj.__proto__ = Class.prototype; let res = Class.call(obj); return typeof res === "object" ? res : obj; }call 實(shí)現(xiàn)
Function.prototype.callfb = function (ctx) { if (typeof this !== "function") { throw new Error("Function undefined"); } ctx = ctx || window; const fn = ctx.fn; ctx.fn = this; const args = [...arguments].slice(1); const res = ctx.fn(...args); ctx.fn = fn; return res; }apply 實(shí)現(xiàn)
Function.prototype.applyFb = function (ctx) { if (typeof this !== "function") { throw new Error("Function undefined"); } ctx = ctx || window; const fn = ctx.fn; ctx.fn = this; const arg = arguments[1]; const res = Array.isArray(arg) ? ctx.fn(...arg) : ctx.fn(); ctx.fn = fn; return res; }bind 實(shí)現(xiàn)
Function.prototype.bindFb = function (ctx) { const fn = this; const args = [...arguments].slice(1); const F = function () {}; const fBind = function () { return fn.apply(this instanceof fBind ? this : ctx, args.concat(...arguments)) } if (fn.prototype) { F.prototype = fn.prototype; } fBind.prototype = new F(); return fBind; }instanceof 實(shí)現(xiàn)
function instanceofFb(left, right) { let proto, prototype = right.prototype; proto = left.__proto__; while (proto) { if (proto === prototype) { return true; } proto = proto.__proto__; } return false; }Promise 實(shí)現(xiàn)
function promiseFb(fn) { const _this = this; this.state = "pending"; // 初始狀態(tài)為pending this.value = null; this.resolvedCallbacks = []; // 這兩個(gè)變量用于保存then中的回調(diào),因?yàn)閳?zhí)行完P(guān)romise時(shí)狀態(tài)可能還是pending this.rejectedCallbacks = []; // 此時(shí)需要吧then中的回調(diào)保存起來方便狀態(tài)改變時(shí)調(diào)用 function resolve(value) { if (_this.state === "pending") { _this.state = "resolved"; _this.value = value; _this.resolvedCallbacks.map(cb => { cb(value) }); // 遍歷數(shù)組,執(zhí)行之前保存的then的回調(diào)函數(shù) } } function reject(value) { if (_this.state === "pending") { _this.state = "rejected"; _this.value = value; _this.rejectedCallbacks.map(cb => { cb(value) }); } } try { fn(resolve, reject); } catch (e) { reject(e); } } promiseFb.prototype.then = function (onFulfilled, onRejected) { // 因?yàn)閠hen的兩個(gè)參數(shù)均為可選參數(shù), // 所以判斷參數(shù)類型本身是否為函數(shù),如果不是,則需要給一個(gè)默認(rèn)函數(shù)如下(方便then不傳參數(shù)時(shí)可以透?jìng)鳎? // 類似這樣: Promise.resolve(4).then().then((value) => console.log(value)) onFulfilled = typeof onFulfilled === "function" ? onFulfilled : fn => fn; onRejected = typeof onRejected === "function" ? onRejected : e => { throw e }; switch (this.state) { case "pending": // 若執(zhí)行then時(shí)仍為pending狀態(tài)時(shí),添加函數(shù)到對(duì)應(yīng)的函數(shù)數(shù)組 this.resolvedCallbacks.push(onFulfilled); this.rejectedCallbacks.push(onRejected); break; case "resolved": onFulfilled(this.value); break; case "rejected": onRejected(this.value); break; default: break; } }debounce 防抖
function debounce(fn, wait, immediate) { let timer; return function () { if (immediate) { fn.apply(this, arguments); } if (timer) clearTimeout(timer); timer = setTimeout(() => { fn.apply(this, arguments); }, wait) } }throttle 節(jié)流
function throttle(fn, wait) { let prev = new Date(); return function () { const now = new Date(); if (now - prev > wait) { fn.apply(this, arguments); prev = now; } } }雙向綁定
雙向綁定:視圖(View)的變化能實(shí)時(shí)讓數(shù)據(jù)模型(Model)發(fā)生變化,而數(shù)據(jù)的變化也能實(shí)時(shí)更新到視圖層.
Object.definePropertyProxymvvm 數(shù)據(jù)值:
算法 冒泡排序mvvm 數(shù)據(jù)值:
兩兩對(duì)比
function bubble(arr) { const len = arr.length; for (let i = 0; i < len; i++) { for (let j = 0; j < len - i - 1; j++) { if (arr[j] > arr[j + 1]) { let temp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = temp; } } } return arr; }選擇排序
尋找最小的數(shù),將索引保存
function selection(arr) { const len = arr.length; let minIndex, temp; for (let i = 0; i < len - 1; i++) { minIndex = i; for (let j = i + 1; j < len; j++) { if (arr[j] < arr[minIndex]) { minIndex = j; } } temp = arr[i]; arr[i] = arr[minIndex]; arr[minIndex] = temp; } return arr; }Webpack 常用loader
file-loader: 加載文件資源,如 字體 / 圖片 等,具有移動(dòng)/復(fù)制/命名等功能;
url-loader: 通常用于加載圖片,可以將小圖片直接轉(zhuǎn)換為 Date Url,減少請(qǐng)求;
babel-loader: 加載 js / jsx 文件, 將 ES6 / ES7 代碼轉(zhuǎn)換成 ES5,抹平兼容性問題;
ts-loader: 加載 ts / tsx 文件,編譯 TypeScript;
style-loader: 將 css 代碼以