几个前端基础面试题
-
关于作用域和自由变量的场景题
let i; for (i = 1; i <= 3; i++ ) { setTimeout(function(i) { console.log(i); },0); } 以上代码输出什么?
如何修改,让上面代码输出1,2,3
方案一:
for(let i = 1; i <= 3; i++) { setTimeout(function(){ console.log(i); },0) }
方案二:
// 使用立即执行函数 let i; for (i = 1; i <= 3; i++) { (function(j) { setTimeout(function() { console.log(j); }, 0); })(i); }
方案三
// 借用setTimeout()的参数传入 let i; for (i = 1; i <= 3; i++) { setTimeout(function(j) { console.log(j); }, 0, i) }
-
判断字符串以字母开头,后面字母数字下划线,长度6-30 (知识点:正则)
const reg = /^[a-zA-Z]w{5-29}$/
-
手写trim,保证浏览器的兼容
// 干掉开头和结尾的空格 Strig.prototy.trim = function () { return this.replace(/^s+/,"").replace(/^s+$/,''); } //知识点 原型 this 正则表达式
-
如何获取多个数字中的最大值
function max() { const nums = Array.prototype.slice.call(arguments); let max = 0; nums.forEach(item=>{ if (n > max) max = n; }); return max; }
用Math.max()
function max() { return Math.max(Array.prototype.slice.call(arguments)); }
-
JS的继承?
// extends class 继承 // prototype 继承
-
如何捕获异常
- 手动捕获:
try { } catch(ex) { } finally { }
- 自动捕获
window.onerror = function (message , source , lineNum, colNum, error ) { // 第一, 对于跨域的js ,如cdn不会有详细的报错信息 // 第二, 对于压缩的js , 要配合sourceMap 反查未压缩的代码行和列 }
-
JSON
- 是一种数据格式,本质是一种字符串
- json格式和JS对象结构一致,对JS语言相当的友好
- window.JSON是一个全局对象,JSON.parse() , JSON.stringigy()
-
获取当前页面的url参数
//正则匹配来获取 function query(name ) { //去除? const search = location.href.substr(1); const reg = new RegExp(`(^|&)${name}=([^&]*)(&|$)`,'i'); const res = search.match(reg); if (!res) { return null; } return res[2]; }
//使用URLSearchParams function query(name) { const search = location.search; return new URLSearchParams(search).get(name); }
// 使用split对字符串进行拆分 function query(name) { const search = location.serach.substr(1); search.split("&").forEach(item=>{ const arr = item.split('='); if (arr[0] === name) { return arr[1]; } }); return null; }
-
数组去重的方式
使用Set---无序结构,不可重复
let unique = (arr)=>[...new Set(arr)];
遍历
function unique(arr) { const res = []; arr.forEach(item => { // indexOf 也是遍历 if (res.indexOf(item) < 0) { res.push(item); } }); return res; } // O(n^2)
-
手写falt,考虑多层级, 就是拍平数组
function flat(arr) { const isDeep = arr.some(item=>item instanceof Array); if (!isDeep) return arr; // 递归 const res = Array.prototype.concat.apply([],arr); return flat(res); }
-
将url参数解析为JS对象
function queryToObj() { const res = {}; const search = location.serach.substr(1); search.split("&").forEach(item=>{ const arr = item.split('='); res[arr[0]] = arr[1]; }); return res; }
-
手写深拷贝
function deepClone(obj) { if (typeof obj !== 'object' || obj == null) { return obj; } let cloneObj = Array.isArray(obj)?[]:{}; for (let key in obj) { if (obj.hasOwnProperty(key)) { if (obj[key] && typeof obj[key] === 'object') { cloneObj[key] = deepClone(obj[key]); } else { cloneObj[key] = obj[key]; } } } return cloneObj; }
function deepClone(obj) { const cloneObjStr = JSON.stringify(obj); return JSON.parse(cloneObjStr); }
Object.assign不是深拷贝,只是拷贝第一层级的拷贝
-
RAF requesAnimationFrame
动画 60帧每秒 16.67ms更新
RAF 浏览器会自动控制 setTimeout手动控制
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> #div1 { 100px; height: 50px; background-color: red; } </style> </head> <body> <p>JS真题演示</p> <div id="div1"></div> <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.js"></script> <script src="./RAF.js"></script> </body> </html>
// 浏览器能够自动控制 const $div1 = $('#div1'); const currentWidth = 100; const maxWidth = 640; function animate() { currentWidth = currentWidth + 3; $div1.css('width',currentWidth); if (currentWidth < maxWidth) { window.requestAnimationFrame(animate); } } animate();
// 硬核动画, 自己动手写 function animate() { currentWith += 3; $div1.css('width',currentWidth); if (currentWidth < maxWidth) { setTimeout(animate,16.3); } } animate();
-
前端性能优化