1. 程式人生 > 實用技巧 >2021-01-08(今日筆記)

2021-01-08(今日筆記)

1、css 前處理器(sass/less)

原理:是將類css語言通過 webpack 編譯轉成瀏覽器可讀的真正css。常用功能:
巢狀
變數
迴圈語句
條件語句
自動字首
單位轉換
mixin複用

2、css動畫

transition:過渡動畫
transition-property:屬性
transition-duration:間隔
transition-timing-function: 曲線
transition-delay:延遲

animation/keyframes:
animation-name:動畫名稱,對應 @keyframes
animation-duration:間隔
...

動畫屬性:儘量使用動畫屬性進行動畫
translate
scale
rotate
skew

3、原型/建構函式/例項

原型(prototype):一個簡單的物件,用於實現物件的屬性繼承。每個js物件中都包含一個 __proto__的
屬性指向它爹(該物件的原型),可 obj.__proto__ 進行訪問。

建構函式:可以通過 new 來新建一個物件的函式。

例項:通過建構函式和new創建出來的物件,便是例項。例項通過 __proto__ 指向原型,通過constructor
指向建構函式。

//例項
const instance = new Object()
例項為 instance,建構函式為object,建構函式擁有一個prototype的屬性指向原型。
//原型
const prototype = Object.prototype

例項.__proto__ === 原型
原型.constructor === 建構函式
建構函式.prototype === 原型
例項.constructor === 建構函式


原型鏈:
原型鏈是由原型物件組曾,每個物件都有 __proto__ 屬性,指向了建立物件的建構函式的原型,__proto__
將物件連線起來組成了原型鏈。是一個用來實現繼承和共享屬性的有限的物件鏈。

執行上下文:(EC 可以理解為一個物件)
包含三個部分:
變數物件VO
作用域鏈(詞法作用域)
this指向
型別:
全域性執行上下文
函式執行上下文
eval執行上下文
程式碼執行過程:
建立 全域性上下文global EC;
全域性執行上下文逐行自上而下執行。
函式執行上下文被啟用,成為active EC,開始執行函式中的程式碼,caller被掛起
函式執行完成後,callee 被pop移除執行棧,控制權交還全域性上下文caller,繼續執行。


作用域:
執行上下文中包含作用域鏈。作用域其實可以理解為該上下文中宣告的 變數和宣告的作用範圍。分為 塊級作用
域和函式作用域。
特性:
宣告提前:一個宣告在函式體內都是可見的,函式優先於變數。
非匿名執行函式,函式變數為 只讀 狀態,無法修改。
let fun = function(){console.log('func')}
(function fun(){ fun = 10;console.log(fun) }()) ;//這裡會輸出: f fun(){fun=10;
console.log((fun)}


閉包:
(定義)父函式被銷燬的情況下,返回出的子函式的[[scope]]中仍然保留著父級的單變數物件和作用域鏈,因此可以
繼續訪問到父級的變數物件。

會產生的問題:多個子函式的[[scope]]都是同時指向父級,是完全共享的。因此當父級的變數物件被修改時,
所有子函式都受到影響。

解決:
變數可以通過 函式引數的形式 傳入,避免使用預設的[[scope]]向上查詢。
使用 setTimeout 包裹,通過第三個引數傳入
使用塊級作用域,讓變數成為自己上下文的屬性,避免共享。


script 引入方式:
靜態<script>引入
js動態插入<script>
<script defer>:延遲載入,元素解析完成後執行
<script async>:非同步載入,但執行時會阻塞元素渲染


物件的拷貝:
淺拷貝:以賦值的形式拷貝引用物件,仍指向同一個地址,修改時原物件也會受到影響。
Object.assign
展開運算子(...)
深拷貝:完全拷貝一個新物件,修改時原物件不再受到任何影響。
JSON.parse(JSON.stringify(obj)):效能最快。
遞迴進行逐一賦值。


new 運算子的執行過程:
新生成一個物件
連結到原型:obj.__proto__ = Con.prototype
繫結 this: apply
返回新物件。


程式碼複用方式:
函式封裝,
繼承,
複製extend
混入mixin
借用apply/call

3、let, const 以及 var 的區別?

es5只有全域性作用域和函式作用域,沒有塊級作用域。
es6中增加了塊級作用域的概念。

let命令:
用來宣告變數,但是所宣告的變數,只在let命令所在的程式碼塊內有效。
不存在變數提升。(var命令會發生'變數提升'現象,即變數可以在宣告之前使用,值為undefined。)
不允許重複宣告。
暫時性死區(只要塊級作用域記憶體在let命令,它所宣告的變數就繫結這個區域,不再受外部的影響。在程式碼塊
內,使用let命令宣告變數之前,該變數都是不可用的。temporal dead zone => TDZ)

const:
宣告一個只讀的常量。一旦宣告,常量的值就不能改變。
const 一旦宣告變數,就必須立即初始化,不能留到以後賦值。對於const來說,只宣告不賦值,就會報錯。
const命令宣告的常量也是不提升,同樣存在暫時性死區,只能在宣告的位置後面使用。
const 的作用域與let命令相同:只在宣告所在的塊級作用域內有效。

var:變數提升(無論宣告在何處,都會被提至其所在作用域的頂部。
let:無變數提升(未到let宣告時,是無法訪問該變數的)
const:無變數提升,宣告一個基本型別的時候為常量,不可修改;宣告物件可以修改。

4、HTTP常見狀態碼

HTTP狀態碼錶示客戶端HTTP請求的返回結果,標記伺服器端的處理是否正常或者是出現的錯誤,能夠根據返回的狀態
碼判斷請求是否得到正確的處理。

1xx 資訊性狀態碼: 接受的請求正在處理
2xx 成功狀態碼: 請求正常處理完畢
200 -> ok
204 -> no content: 表示客戶端傳送請求得到處理,但在返回的響應報文中不含實體的主體部分。

3xx 重定向 需要進行附加操作已完成請求
301 -> moved permanently: 永久性重定向,表示請求的資源被分配了新的url,之後應使用更改的url。
302 -> found:臨時性重定向
304 -> not modified: 表示客戶端傳送附帶條件的請求時,服務端允許訪問資源。
4xx 客戶端錯誤 客戶端請求出錯,伺服器無法處理請求
400 ->bad request:請求報文中存在語法錯誤
401 ->unauthorized:未經許可,需要通過HTTP認證
403 ->forbidden:伺服器拒絕該次訪問
404 ->not found: 表示伺服器上無法找到請求的資源。
5xx 伺服器錯誤 伺服器處理請求出錯

5、vuex

vuex 是一個專門為vue.js應用設計的狀態管理構架,統一管理和維護各個元件的可變化狀態。
五個核心概念:
state: vuex的基本資料,用來儲存變數
getter:從基本資料state派生的資料,相當於state的計算屬性
mutation:提交更新資料的方法,必須是同步的(非同步可使用action)
action:非同步操作
modules:模組化vuex,可以讓每一個模組都擁有自己的state,mutation等,方便管理。

6、防抖/節流

高頻觸發優化方式,能對效能有較大的幫助。

防抖(debounce):將多次高頻操作優化為只在最後一次執行,通常使用的場景是:使用者輸入,只需要再輸入完成後做一次
校驗即可。
function debounce(fn,wait,immediate){
let timer = null;
return function(){
let args = arguments;
let context = this;
if(immediate && !timer){
fn.apply(context,args)
}
if(timer) clearTimeout(timer)
timer = setTimeout(()=>{
fn.apply(context,args)
},wait)
}
}

節流:每隔一段時間後執行一次,也就是降低頻率,將高頻操作優化成低頻操作,通常使用場景:滾動條事件或者resize
事件,通常每隔100-500ms執行一次即可。
function throttle(fn,wait,immediate){
let timer = null;
let callNow = immediate
return function(){
let context = this,
args = arguments;
if(callNow){
fn.apply(context,args);
callNow = false
}
if(!timer){
timer = setTimeout(()=>{
fn.apply(context,args)
timer = null;
},wait)
}
}
}

7、函式執行改變this

在函式中,可以引用執行環境中的變數。就需要一個機制來讓我們在函式體內部獲取當前的執行環境,即this。
this指向,即誰呼叫了函式。例如
obj.fn(),便是obj呼叫了函式,即函式中的this === obj;
fn(),即window.fn(),因此 this === window;

手動修改this的指向,即:
call: fn.call(target,1,2)
apply: fn.apply(target,[1,2])
bind: fn.bind(target)(1,2)
共同點:第一個引數都是this要指向的物件,都可以利用後續引數傳參,都可以改變this指向。
不同點:
call 和 apply 都是對函式的直接呼叫,而bind方法返回的仍然是一個函式,因此後面需要()進行呼叫才可以。
call後面的引數與func方法中是一一對應的,apply的第二個引數是一個數組,陣列中的元素和func方法中一一對應。
由於bind返回的仍然是一個函式,所以我們可以在呼叫的時候進行傳參。
例如:
var obj = {
name:'xx',
age:18,
say:function(param1,param2){
console.log(this.name +',今年'+ this.age+'歲,'+params1 + param2)
}
}
var obj2 = {
name:'yy',
name:'20'
}
obj2.say.call(obj1,'hello','world')
obj2.say.apply(obj1,['hello','world'])
obj2.say.bind(obj1)('hello','world')

8、ES6/ES7

宣告
let/const:塊級作用域,不存在變數提升,暫時性死區,不允許重複宣告
const:宣告常量,無法修改
解構賦值
class/extend:類宣告與繼承
set/map:新的資料結構
非同步解決方案:
promise 的使用與實現
generator:
yield:暫停程式碼
next():繼續執行程式碼

function* helloworld(){
yield 'hello';
yield 'world';
return 'ending';
}
const generator = helloworld();
generator.next() //{value:'hello',done:false}
generator.next() //{value:'world',done:false}
generator.next() //{value:'ending',done:false}
generator.next() //{value:undefined,done:true}

await/async: 是generator的語法糖,Babel中是基於promise實現。

async function getUserByAsync(){
let users = await fetchUser();
return users;
}
const user = await getUserByAsync()
console.log(user,'user')

9、函式柯里化

在一個函式中,首先填充幾個引數,然後再返回一個新的函式的技術,稱為函式的柯里化。
const add = function add(x){
return function(y){
return x+y
}
}
const add1 = add(1);
add1(2) => 3

10、陣列 array

map:遍歷陣列,返回回撥返回值組成的新陣列
forEach:無法break,可以用try/catch 中 throw new Error 來停止。
filter:過濾
some:有一項返回true,則返回true
every:有一項返回false,則返回false。
join:通過指定連線符生成字串
push/pop:末尾新增和刪除,改變原陣列。
unshift/shift:頭部新增和刪除,改變原陣列。
sort(fn)/reverse:排序與反轉,改變原陣列
concat:連線陣列,不影響原陣列,淺拷貝
slice(start,end):返回截斷後的新陣列,不改變原陣列
splice(start,number,value...):返回刪除元素組成的陣列,value為插入項,改變原陣列
indexOf/lastIndexOf(value,formIndex):查詢陣列項,返回對應的下標
reduce/reduceRight()

陣列亂序:
var arr = [1,2,3,4,5,6,7,8,9,10]
arr.sort(function({
return Math.random() - 0.5;
})
陣列拆解:flat:[1,[2,3]] ->[1,2,3]
Array.prototype.flat = function(){
return this.toString.split(',').map(item => +item)
}

11、從輸入url到頁面展示的過程

DNS解析
TCP三次握手
傳送請求,分析url,設定請求報文(頭,主體)
伺服器返回請求的檔案html
瀏覽器渲染(html css layout佈局...)

12、迴流必定觸發重繪,重繪不一定觸發迴流。重繪的開銷較小,迴流的代價較高。

13、儲存

儲存分為短暫性儲存和永續性儲存
短暫性儲存:將資料存在記憶體中,只在執行時用即可。
永續性儲存:分為瀏覽器端和伺服器端。
瀏覽器:
cookie:通常用於儲存使用者身份,登入狀態等。(體積上限4k,可自行設定過期時間)
localStorage/sessionStorage:長久儲存/視窗關閉刪除,體積限制4-5M
indexDB
伺服器:
分散式快取redis
資料庫

14、記憶體洩露

意外的全域性變數:無法被回收
定時器:未被正確關閉,導致所引用的外部變數無法被釋放
事件監聽:沒有正確銷燬
閉包:導致父級中的變數無法被釋放
dom引用:dom元素被刪除時,記憶體中的引用未被正確清空

15、get/post

get:快取,請求長度受限,會被歷史儲存記錄
post:安全,大資料,更多編碼型別。

16、websocket

websocket 是一個持久化協議,基於http,服務端可以主動push。

new WebSocket(url)
ws.onerror = fn
ws.onclose = fn
ws.onopen = fn
ws.onmessage = fn
ws.send()

17、TCP三次握手,四次揮手

建立連線前,客戶端和服務端需要通過握手來確認對方:
客戶端傳送syn(同步序列編號)請求,進入 syn_send 狀態,等待確認。
服務端接收並確認syn包後傳送 syn+ack包,進入 syn_recv狀態
客戶端接收 syn+ack 包後,傳送 ack 包,雙方進入 established 狀態。

四次揮手:
客戶端 -FIN ->服務端,FIN-WAIT
服務端 -ACK ->客戶端,CLOSE-WAIT
服務端 -ACK,FIN ->客戶端,LAST-ACK
客戶端 -ACK ->服務端,CLOSED

18、跨域

JSONP: 利用 <script>標籤不受跨域限制的特點,缺點是隻能支援get請求
function jsonp(url,jsonpCallback,success){
const script = document.createElement('script')
script.src = url
script.async = true
window[jsonpCallback] = function(data){
success && successs(data)
}
document.body.appendChild(script)
}

設定 CORS: Access-Control-Allow-Origin:'*'
postMessage

參考連結:https://juejin.cn/post/6844903776512393224#heading-16