// 判斷數組對象特定屬性是否相同 function isEqualObj(arr, key) { const newArr = arr.map(item => item[key]) const arrSet = new Set(newArr) return arrSet.size !== newArr.length } // js 繼承有四種 原型鏈繼承, 構造函數繼承, 組合繼承,寄生繼承 // 原型繼承,改了其中一個實例會影響其它的,構造函數繼承不到父類的屬性和方法 //組合繼承 function chidren(name) { this.name = name } chidren.prototype.getName = function() { return this.name } function inhert() { // 構造函數繼承 chidren.call(this,'王二') } inhert.prototype = new chidren() // inhert.prototype = Object.create(chidren.prototype) //將指向父類實例改爲指向父類原型 爲寄生繼承 inhert.prototype.constructor = inhert // 使用 const inhert1 = new inhert() inhert1.name // ['王二'] // 數組去重 function removeDuplicate(arr, key) { let obj = {} const curArr = arr.reduce((pre, cur)=> { obj[pre[key]] ? '' : obj[pre[key]] = true && pre.push(cur) return pre },[]) return curArr } // 實現sleep(1000) const sleep = time => { return new Promise((resolve) => { resolve(setTimeout(() => { console.log('time'); }, time)) }) } // 使用 sleep(1000).then(res => { console.log(res); }) // 手動實現bind Function.prototype.myBind = function() { // 不能使用箭頭函數,應爲this的指向不同 // arguments 可以獲取函數的所有參數,是一個僞數組, 使用Array.from() 將 僞數組轉換成數組 const arg = Array.from(arguments) // 獲取this 指向取出數組的第一項,數組剩餘的就是傳遞的參數 const self = this return () => { return self.apply(_this,arg) } } // 使用 function fn1(a, b, c) { console.log('this',this); console.log(a,b,c); } const fn2 = fn1.myBind(10,20,30) console.log(fn2); // 手動實現call Function.prototype.myCall = function() { const fn = Symbol('fn') // 聲明一個獨有的symbol屬性,防止fn覆蓋已有屬性 thisArg = thisArg || window // 如沒有傳入this,默認綁定到window thisArg[fn] = this // this 指向調用call的對象,即我們要改變this指向的函數 const result = thisArg[fn](...args) // 指向當前函數 delete thisArg[fn] // 刪除聲明的fn屬性 return result } // 並集,交集,差集 let set1 = new Set([1,2,3]) let set2 = new Set([2,3,4]) // 並集 let union = new Set([...set1, ...set2]) // 交集 let interset = new Set([...set1].filter(x => set2.has(x))) // 差集 let difference = new Set([...set1].filter(x=> !set2.has(x))) // 克隆 function deepClone(obj) { if (!obj || typeof obj !== 'object') return const data = Array.isArray(obj) ? [] : {} for (let i in obj) { data[i] = typeof(obj[i]) === 'object' ? deepClone(obj[i]) : obj[i] } return data } // 去重 function removeRepeat(arr, key) { let obj = {} const cur = arr.reduce((pre,cur) => { obj[cur[key]] ? '' : obj[cur[key]] = true && pre.push(cur) return pre },[]) return cur } // 求和 function sum(arr) { let data = arr.reduce((pre,cur) => { return pre + cur },0) } // 防抖是在事件觸發後n秒再去執行回調,如果n秒內再次被觸發,則重新計算,最常用 搜鎖框輸入查詢,表單提交 function debouce(fn, wait) { let time = null return function() { time && clearTimeout(time) time = setTimeout(() => { fn.apply(this, arguments) }, wait); } } // 節流 是指如果頻繁觸發一個事件,則n秒後執行一次 function throttle(fn, wait) { let flag = true return function() { if (!flag) return flag = false setTimeout(() => { fn.apply(this, arguments) flag = true }, wait); } } // 計算 1+2+3...100 function sumByValue(val) { if (val === 1) return return sumByValue(val -1) + val } // Set 和Map的區別是,Set類似於數組,每一個值是唯一的,Map類似於對象,是鍵值對的集合 // AMD require 是運行時調用,可以用在任何地方,是賦值的過程可以是數組,對象,字符串 // CMD import 是編譯是調用,所以必須用於開頭,是解構的過程 // 通常緩存,分爲協商緩存和強制緩存 // 強制緩存: 1.瀏覽器控制 2.後端把過期時間和資源發過來,瀏覽器每次獲取資源看一下過期時間到了沒 // 協商緩存: 1.服務器控制 2.後端把資源標識,和資源發送過來,瀏覽器每次用的時候,就會拿標識和後端存儲的對比一下不一樣就更新 // 強制緩存使用時間來判斷,時間分爲相對時間和絕對時間 // 絕對時間 expires字段 // 相對時間 後端給有效時長,瀏覽器自己倒計時,對應着請求的cach-control字段,同時存在。cach-control優先級更高 // js垃圾回收,就是標記清除和引用計數 // js中 ! 和 !! !將變量轉換成boolen類型,!!常常用來做類型判斷,在第一步!之後再做邏輯取反運算, ??只有在左側爲null和undefiend時,纔會返回右側數據 // 漸進式圖片加載 antimoderate // aligin-self: baseline // vue中定義props類型,Proptype // [1,2,3].map(parseInt) 結果時[1,NAN,NAN] 原因是,最終會轉換成 arr.map((value,index, array) => parseInt(value,index)) // flex:1 對應這flex-grow(拉伸佔比) flex-shrink(收縮規則,0 爲不收縮) flex-basis(主軸方向初始大小) // 迴流,當元素尺寸,位置發生變化需要重新計算。 重繪: 當元素DOM樣式發生變化,沒有影響到DOM的幾何尺寸 // GET和POST 請求的區別: 1. get請求在url上,post在請求體中 2.get請求有長度限制(瀏覽器限制的) 3.post請求相對安全點,get請求在url上,且有歷史記錄 4. get請求能緩存,post不能 // HTTPS使用443端口,HTTP使用80端口 2. http是超文本傳輸協議,是明文傳輸,https是經過SSL加密協議,傳輸更安全,不過要申請證書 3. https比http慢因爲,除了tcp握手的三個包,還有ssl加密的9個包 // http1.1和http2.0區別: 1.1使用基於文本的格式傳輸,2.0使用二進制傳輸, 1.1不支持header數據壓縮,2.0使用hpack算法對header進行數據壓縮,體積更小,傳輸更快 // http 請求狀態碼總結 // 1** 服務器接收請求,需要請求者接着操作 // 2** 請求成功 // 3** 重定向,需要進一步操作 // 4** 客戶端錯誤,請求包含語法錯誤,無法完成請求 // 5** 服務器錯誤 // 從瀏覽器輸入url頁面發生了什麼? // 1. DNS查詢,解析url中對應的ip地址 2.tcp鏈接 3.發送http請求 4.server處理http請求,並返回http保文 5. 瀏覽器解析,render頁面 6. http斷開鏈接 // VUE中diff算法: // VUE根據真實dom生成一個virtural DOM ,當virtral DOM 的某個節點數據改變後會生成一個新的Vnode,然後Vnode和 oldVnode做對比,發現不一樣就直接更新dom,然後oldVnode的職位Vnode, // 來實現節點更新。 具體是: 1.同級比較再比較字節點 2. 先判斷一方是否有子節點,如果新的的沒有子節點,就將舊的字節點移除掉 3.都有子節點的情況,遞歸比較子節點 // VUE中key的作用,儘可能的複用dom元素,新舊節點如果只有順序不同,最佳是通過移動位置達到更新目的,需要再節點保持映射關係,key就是節點中的唯一標識 // VUE中template的編譯原理 1. 將模板字符串轉換成element Asts解析器 2. 對ast進行靜態節點標記,主要用來虛擬dom的優化 3.使用element ast生成render函數代碼字符串 // nextTick 是更新執行完成之後的回調,主要是宏任務和微任務,根據不同的情況,採用 promise MutationServer 微任務 promise 都不用就使用setTimeout // .stop禁止事件冒泡, .prevert 阻止默認事件, .self 只有點擊元素本身才會執行 .capture事件觸發,會先執行大盒子的事件再執行小盒子的事件,.once只觸發一次 // data爲什麼是一個函數,對象再棧中存放的都是對象的地址,函數的作用,就是屬性私有化,保證組件修改自身的屬性不會影響到其它組件
// VUE中keep-alive實現原理和緩存策略:
// 1.獲取keep-alive的第一個組件 2. 根據include和 exclude名單進行匹配,決定是否緩存,不匹配直接返回組件實例,匹配進行第3步 3. 根據組件id和tag生成緩存組件的key,再去判斷cache中是否存在這個key,如果存在,則用緩存的實例代替Vnode的
// 的實例,然後更新key再keys的位置(LRU置換策略),如果沒有命中就緩存起來,如果超出最大緩存數,就刪除cache中的第一項 4. keep-alive是一個抽象組件:自身不會渲染DOM元素,也不會出現再父組件鏈中 5.LRU算法:根據
// 數據的歷史訪問記錄來進行數據淘汰,其實就是訪問過的,以後訪問率會高 6. LRU實現,新數據插入鏈表頭部,每當緩存命中,則將數據移至鏈表頭部,當鏈表滿的時候,則將鏈表尾部數據丟棄
// vue-router的實現原理:單頁應用只有一個頁面,所有的頁面切換,其實是組件之間的顯示和隱藏,所有的頁面都只在一個html頁面上,
// vue-router是通過對window.location.hash和windown.history進行封裝,來實現hash或url變化映射組件的變化
// vue-router 前端路由的核心就是改變視圖的同時不會向後端發送請求,而是加載對應的而組件, 有兩種模式 hash和history。 hash模式在url後面帶有#,hash值會出現在#後面,但是不包含在http請求中,hash改變會
// 觸發hashChage事件,能控制瀏覽器的前進後退,兼容性好 缺點是: 包好#不美觀, 設置的值必須與原來的值不一樣纔會觸發hashChange, 每次url改變不屬於一次http請求,不利於seo優化
// history 基於pushState()和replaceState()來實現改變頁面路徑,histoty是瀏覽器提供的歷史記錄接口,可以通過back go forward讀取歷史記錄
// for of 無法遍歷對象,forEach和map都只能遍歷數組,不能終端,前者沒有返回值,後者有 // JS中 宏任務一般包含 scpirt setTimeout setInterval 微任務: promise preocess.nextTick , promise 是同步任務 then是異步任務 // 什麼是事件循環: js是單線程語言,同個時間執行一件事(同步),但它可以有一個異步隊列,遇到異步操作,(如axios這種阻塞時間久的),把它放到異步隊列中,並繼續往下執行,當同步任務執行 // 完成,就會去異步隊列中找剛剛存放的事件依次執行(異步任務包含宏任務和微任務,微任務優先於宏任務) // VUE3自定義v-model // 父組件中使用 <test v-model:title ="value" /> //子組件中定義 <div :title="title" @update:title="title = $event">{{title}}</div> emit('update:title',t.value) // vue2自定義v-model mode: { event: 'change', prop: 'check' } // rem相對於根元素 如果font-size = 16px,那 // 監聽屏幕大小 window.onresize = function() { // 獲取屏幕寬度 let w = document.documentElement.clientWidth || document.body.clientWidth // 根據設計圖設置大小 HTML.style.fontSize = 16 * (w / 750) + 'px' } // iphonex 適配當viewport-fit = contain 時,env() 是不起作用的 必須配合 viewport-fit-cover // env() 和 constant() 需要同時存在,且順序不能換 paading - bottom: containsPoint(safe - area -inset -bottom); paading - bottom: event(safe -area -inset - bottom)