寫在前面:html
一年沒有面試了,約了一個外包面試,去大廠,就當我去檢測我這1年的成果了。前端
var a = 1 function a() { return 2 } console.info(a) // 1 console.info(typeof a) // number
for(var i = 0; i < 3; i++) { setTimeout(function() { console.info(i) }); } // 3 3 3
實現一個方法,將有序的數組變爲亂序es6
// 解法一 function getRandomArr(arr) { let len = arr.length let randomIndex = Math.floor(Math.random() * len) let temp while(len >= 0) { temp = arr[randomIndex] arr.splice(randomIndex, 1) arr.push(temp) len-- randomIndex = Math.floor(Math.random() * len) } return arr }
// 解法二 function getRandomArr(arr) { /* 每次循環時都要與第i項互換位置 */ for (var i = 0; i < arr.length; i++) { var j = parseInt(Math.random() * arr.length) /* 將所獲取的數和第i個數互換位置 */ var temp = arr[i] arr[i] = arr[j] arr[j] = temp } return arr }
// 解法三 function getRandomArr(arr) { arr.sort(() => { return (0.5-Math.random()) }) return arr }
實現一個綁定DOM事件的js函數,可兼容多種瀏覽器web
<button id="mydiv">點擊觸發事件</button> <script> /* 由於 JavaScript 中全部對象都集成與 Object,那麼只有給Object原型添加一個事件綁定函數, 就不須要在處理綁定事件的時候,每次寫一長串代碼,直接調用便可。 */ // ev 事件屬性 // fn 觸發事件 Object.prototype.addListener = function (ev, fn) { if (this.attachEvent) { // 兼容IE9 IE10 alert('a') this.attachEvent('on' + ev, fn) } else { // 兼容:firefox、chrome、IE、safari、opera alert('v') this.addEventListener(ev, fn, false) } } var mydiv = document.getElementById("mydiv") mydiv.addListener('click', click1, false) function click1() { alert("click1") } </script>
function addEvent(ele, type, func) { if(ele.addEventListener()) { // Chrome ele.addEventListener(type, func) } else { // IE瀏覽器 ele.attachEvent('on' + type, func) } }
首屏最小化chrome
首屏HTML儘可能小,控制DOM節點數、請求數、外鏈數數據庫
元素優化segmentfault
優化落在首屏內的元素性能和結構,包括基礎頁、元素請求、圖片、JS、是否調用第三方內容、層次機構等。數組
頁面靜態化瀏覽器
首屏頁包含了頁面基礎頁時間(第一次請求),以屏內的元素總的DNS解析時間,創建鏈接時間,SSL握手時間,發出請求時間,重定向時間,內容下載時間等。
基礎頁優化 以靜態頁面的形式存放,用戶相關數據依賴Ajax,好比登陸信息。用戶默認顯示未登陸狀態,異步獲取到用戶數據後更新。
首屏按需加載 隱藏tab頁,用了異步加載的方式,只有當用戶正在要看這塊內容的時候纔去拉取。
單獨合併素材 將代發佈的源文件進行壓縮合並,減小文件數量,受權請求最少原則。
統計代碼優化 針對用戶行爲統計代碼如(CNZZ
,百度統計等),進行去除冗餘,統一放到首屏後加載。
輸入過濾。永遠不要相信用戶的輸入,對用戶輸入的數據作必定的過濾。如輸入的數據是否符合預期的格式,好比日期格式,Email格式,電話號碼格式等等。這樣能夠初步對XSS漏洞進行防護。上面的措施只在web端作了限制,攻擊者通抓包工具如Fiddler仍是能夠繞過前端輸入的限制,修改請求注入攻擊腳本。所以,後臺服務器須要在接收到用戶輸入的數據後,對特殊危險字符進行過濾或者轉義處理,而後再存儲到數據庫中。
輸出編碼。服務器端輸出到瀏覽器的數據,可使用系統的安全函數來進行編碼或轉義來防範XSS攻擊。在PHP中,有htmlentities()和htmlspecialchars()兩個函數能夠知足安全要求。相應的JavaScript的編碼方式可使用JavascriptEncode。
安全編碼。開發需儘可能避免Web客戶端文檔重寫、重定向或其餘敏感操做,同時要避免使用客戶端數據,這些操做需儘可能在服務器端使用動態頁面來實現。
WAF(Web Application Firewall),Web應用防火牆,主要的功能是防範諸如網頁木馬、XSS以及CSRF等常見的Web漏洞攻擊。由第三方公司開發,在企業環境中深受歡迎。
.fa { width: 300px; height: 300px; background-color: #f5f5f5; } .son { width: 100px; height: 100px; background-color: #979191; } <div class="fa"> <div class="son"></div> </div>
/* 前提:已知父子div的寬高 */ .fa { overflow: hidden; /* BFC */ } .son { margin: 100px auto; }
.fa { position: relative; } .son { position: absolute; left: 50%; top: 50%; margin-left: -50px; margin-top: -50px; }
.fa { display: flex; justify-content: center; align-items: center; }
.fa { display: grid; grid-template-columns: 33.3% 33.3% 33.3%; grid-template-rows: 33.3% 33.3% 33.3%; } .son { /* 開始於第2條行網格線,結束於第3條行網格線 */ grid-column: 2/3; /* 開始於第2條列網格線,結束於第3條列網格線 */ grid-row: 2/3; }
// 實現一個函數,判斷二維空間中的一個點是否在線段上 // 思路:該點分別到這兩點的距離 是否等於 這倆點距離之和 const pointA = { x: 1, y: 4 } const pointB = { x: 4, y: 1 } let onePoint = { x: 2, y: 3 } let otherPoint = { x: 3, y: 1 } function isInLine(pointA, pointB, target) { let distanceA = distance(pointA, target) let distanceB = distance(pointB, target) let distanceAB = distance(pointA, pointB) return distanceA + distanceB === distanceAB ? 'true': 'false' } function distance(first, second) { let num = Math.pow((first.x - second.x), 2) + Math.pow((first.y - second.y), 2) return Math.round(Math.sqrt(num)) } console.log(isInLine(pointA, pointB, onePoint)) // 'true' console.log(isInLine(pointA, pointB, otherPoint)) // 'false'
當時面試官問我保存的str1
有一個樹形結構:
var data = { key1: 'str1', key2: { key3: 'str3', key4: 'str4', key5: { ket6: 'str6' } } }
實現一個方法getKeys(data, str),獲取字符串 str 在 data 中全部的上級節點名稱,例如:
getKeys(data, 'str1') 返回 'key1'
getKeys(data, 'str3') 返回 'key2 key3'
var data = { key1: 'str1', key2: { key3: 'str3', key4: 'str4', key5: { key6: 'str6', key7: { key8: 'str8' } } // ... } } function getKeys(data, str) { for(let key in data) { if(typeof data[key] == 'string' && data[key] == str) { this.keyName ? this.keyName += key: this.keyName = key return this.keyName } else if(typeof data[key] == 'object') { // keyName += key // keyName += ' ' this.keyName ? this.keyName += key: this.keyName = key this.keyName += ' ' return getKeys(data[key], str) } } } getKeys.prototype.keyName = '' console.info(getKeys(data, 'str8'))
function getKeys(data,str){ var result=[]; function recursion(data,str){ for(var key in data){ if(data[key] == str){ result.push(key); return result; } if(typeof data[key] == 'object'){ result.push(key); return recursion(data[key],str) } } } recursion(data,str);
}
實現一個類,語法能夠是es5 / es6 / es7
調用代碼能夠輸出:item1-1 item2-2 item3-3
調用代碼以下:
var priorityQueue = new PriorityQueue(); priorityQueue.add('item1', 1); priorityQueue.add('item3', 3); priorityQueue.add('item2', 2); priorityQueue.print(); priorityQueue.clear();