文章目录
前言
这部分内容是边听面试课边记录的,写下自己的盲点
有个路线路,看着非常全:https://what-is-fe.gitee.io/
前端路线图
各种小知识点
前端更重视时间复杂度
空间复杂度:
如果是对引入的变量进行保留,虽然定义多个,但依然不高,O(1)
function a(arr=[]){
//O(1)
const ab=arr[1];
const bb=arr[2];
}
如果是与引入变量的长度有关,比如一遍遍历,那就是O(n)
function a(arr=[]){
//O(n)
let arrsub=[];
for(let i in arr){
arrsub[i]=arr[i]+10;
}
}
移动数组k个元素至数组头,时间复杂度O(1)版本
那种循环用pop(),unshift()的方法:时间复杂度O(n^2)–空O(1),性能很差
***unshift()操作,本身就是O(n)的时间复杂度 ***
function move(arr,k){
//时间复杂度O(1)--空间复杂度O(n)
if(arr==false){return arr;}
let step=k%arr.length;
let cur=arr.splice(-step);
return [...cur,...arr]
}
刚刚知道了可以用下面的方式看看代码运行了多长时间
console.time();
restoreIpAddresses(s);
console.timeEnd();
后续以TO表示时间复杂度、SO表示空间复杂度
凡是有序的东西,记得想想二分
二分查找复杂度为O(logn)
链表和数组,哪个实现队列更快
- 数组是连续存储,push很快、shift很慢,用栈实现的话add TO(1)、delete TO(n)
- 链表是非连续存储,查找很慢,但是添加和删除元素快
- 结论:链表实现队列更快
二叉搜索树的第K大元素
- 二叉搜索树的意思:左边节点>root>右边节点
- 注意对root来说,整个左扇都比它小,整个右扇都比它大
- 因此左中右式的中序遍历可以很自然的得到升序结果(从小到大)
为什么是二叉树,而不是三叉树四叉树?
因为二叉树可以二分,二分TO(logn)
注意必须是平衡二叉搜索树(左右都有的)(BBST)在二分搜索时才是O(logn)
如果只有一支,那就退化成了O(n)
红黑树、B树都是二叉搜索树的变种,本质上都是为了使树平衡
var inorderTraversal = function (root) {
中序遍历
let res = [];
const dfs = function (root) {
if (root === null) {
return;
}
dfs(root.left);
res.push(root.val);
dfs(root.right);
}
dfs(root);
return res;
};
堆(heap)
堆是一个完全二叉树
完全二叉树不是满二叉树,在填不满的情况下,完全二叉树优先填左边
堆又分为最大堆和最小堆
最大堆,根节点大于所有的子节点,子节点之间大小无所谓
最小堆与之相反
说明Ajax、Fetch、axios的区别
- 他们都是网络请求技术
- Ajax是一种技术统称,可以不重载整个页面的前提下,更新页面某部分
- Fetch、XMLHttpRequest是API,能直接调用的函数(在浏览器就可以调用)
- axios是一个库(lib),封装了Fetch、XHttpRequest这些API。
超基础面试题:用XMLHttpRequest实现一个ajax
function ajax1(url,callback) {
let xhr = new XMLHttpRequest();
xhr.open("get", url, true);
//第三个参数是同步还是异步,不推荐使用false
xhr.onreadystatechange = function () {
if (xhr.readyState == 4 && xhr.status == 200) {
//请求成功,处理返回结果
callback(xhr.responseText)
}
};
//设置好了onreadystatechange事件,就可以发送请求了
xhr.send();
}
基于fetch实现,fetch基于标准Promise,语法简单,它不是Ajax的封装,而是使用原生js实现的
function ajax2(url) {
return fetch(url).then(res => res.json());
}
防抖(限制执行次数,只执行一次)
- 防抖应用于比如多次点击某个按钮只执行一次,键盘连续输入,最后一次keyUp之后才去搜索等
<div>
<button>点击显示</button>
</div>
<script>
let btn=document.getElementsByTagName("button")[0];
function show(){
console.log("耐心蛰伏、珍惜时间");
}
// function debounce(fn){
// return function(){
// fn();//测试发现,是会立即执行的
// }
// }
function debounce(fn,wait=500){
let timer;
return function(){
if(timer)clearTimeout(timer);
timer=setTimeout(()=>{
fn.apply(this,arguments);
console.log(this)//是button
},wait);
}
}
btn.addEventListener("click",debounce(show,500));
</script>
节流(限制执行频率)
- 节流的使用场景一般是限制频繁发生的事件,比如scroll、resize这样的事件
<div>
<div id="abc" draggable="true" style="background-color: blanchedalmond;width:200px;height:100px;padding:10px;text-align:center;line-height:100px">可拖拽的部件</div>
</div>
<script>
function throttle(fn,delay=100){
let timer;
return function(){
if(timer)return;
timer=setTimeout(()=>{
fn.apply(this,arguments);
timer=0;
},delay);
}
}
const abc=document.getElementById("abc");
abc.addEventListener("drag",throttle((e)=>{
console.log("鼠标的位置"+e.offsetX,e.offsetY);
}),200)
</script>