一、防抖和节流
防抖:单位时间内只执行最后一次,如果在单位时间再次出发,刷新单位时间;
function fangdou(fn, wait) {
let time = null;
return function() {
let context = this;
let args = arguments;
if (time) {
clearTimeout(time);
}
time = setTimeout(function() {
fn.apply(context, args);
}, wait);
};
}
注意:在window里和vue里调用写法不同
vue-methods里
click1: fangdou(function() {
console.log("防抖");
}, 500),
window里
window.onresize = fangdou(() => {
console.log("防抖");
}, 500);
节流:单位时间内只执行一次;
function jieliu(fn, wait) {
let time = null;
return function() {
let context = this;
let args = arguments;
if (!time) {
time = setTimeout(function() {
fn.apply(context, args);
time = null;
}, wait);
}
};
};
click2: jieliu(function() {
console.log("节流");
}, 500),
二,排序与去重
题:let m = [1, 2, 2],n = [2, 3, 3];
返回 m 和n 的不重复的元素,并且按照从小到大排序
//es6
let m = [1, 2, 2];
let n = [2, 3, 3];
const func = (m, n) => Array.from(new Set(m.concat(n))).sort((a, b) => a - b);
console.log(func(m, n));
基本排序算法原理与实现方法详解【插入/选择/归并/冒泡/快速排序】其中冒泡/快速最重要
插入排序
算法描述:
1. 从第一个元素开始,该元素可以认为已经被排序
2. 取出下一个元素,在已经排序的元素序列中从后向前扫描
3. 如果该元素(已排序)大于新元素,将该元素移到下一位置
4. 重复步骤 3,直到找到已排序的元素小于或者等于新元素的位置
5. 将新元素插入到该位置后
6. 重复步骤 2~5选择排序
算法描述:直接从待排序数组中选择一个最小(或最大)数字,放入新数组中。
编程思路:先假设第一个元素为最小的,然后通过循环找出最小元素,然后同第一个元素交换,接着假设第二个元素,重复上述操作即可
选择排序
算法描述:直接从待排序数组中选择一个最小(或最大)数字,放入新数组中。
编程思路:先假设第一个元素为最小的,然后通过循环找出最小元素,然后同第一个元素交换,接着假设第二个元素,重复上述操作即可
归并排序
算法描述:
1. 把 n 个记录看成 n 个长度为 l 的有序子表
2. 进行两两归并使记录关键字有序,得到 n/2 个长度为 2 的有序子表
3. 重复第 2 步直到所有记录归并成一个长度为 n 的有序表为止。
快速排序
算法描述:
- 在数据集之中,选择一个元素作为”基准”(pivot)。
- 所有小于”基准”的元素,都移到”基准”的左边;所有大于”基准”的元素,都移到”基准”的右边。这个操作称为分区 (partition)操作,分区操作结束后,基准元素所处的位置就是最终排序后它的位置。
- 对”基准”左边和右边的两个子集,不断重复第一步和第二步,直到所有子集只剩下一个元素为止。
【性能】:快速排序是不稳定排序,时间复杂度为O(nlogn)。快速排序是通常被认为在O(nlog2n)的排序方法中平均性能最好的,但最坏情况下快速排序退化为O(n^2)。
function
quickSort(arr){
function
swap(arr,right,left){
var
tmp = arr[right];
arr[right]=arr[left];
arr[left]=tmp;
}
function
partition(arr,left,right){
//分区操作,
var
pivotValue=arr[right]
//最右面设为标准
var
storeIndex=left;
for
(
var
i=left;i<right;i++){
if
(arr[i]<=pivotValue){
swap(arr,storeIndex,i);
storeIndex++;
}
}
swap(arr,right,storeIndex);
return
storeIndex
//返回标杆元素的索引值
}
function
sort(arr,left,right){
if
(left>right)
return
;
var
storeIndex=partition(arr,left,right);
sort(arr,left,storeIndex-1);
sort(arr,storeIndex+1,right);
}
sort(arr,0,arr.length-1);
return
arr;
}
冒泡排序
算法描述:
1. 比较相邻的元素。如果第一个比第二个大,就交换他们两个。
2. 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。
3. 针对所有的元素重复以上的步骤,除了最后一个。
4. 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。【性能】:冒泡排序是稳定排序,时间复杂度为O(n^2),不需要额外空间。
function
bubbleSort(arr){
var
len=arr.length;
for
(
var
i=len-1;i>0;i--){
for
(
var
j=0;j<i;j++){
if
(arr[j]>arr[j+1]){
var
tmp = arr[j];
arr[j]=arr[j+1];
arr[j+1]=tmp
}
}
}
return
arr;
}
三,二叉树(前端最常考察的就是二叉树!)
二叉树在计算机科学中应用很广泛,学习它有助于让我们写出高效的插入、删除、搜索节点算法。二叉树的节点定义:一个节点最多只有两个节点,分别为左侧节点、右侧节点。
二叉搜索树是二叉树中的一种,在二叉搜索树中每个父节点的键值要大于左边子节点小于右边子节点。下图展示一颗二叉搜索树。
二叉搜索树实现大纲
- constructor():构造函数,初始化一个二叉搜索树
- insert(value):二叉树中查找一个节点,如果存在返回 true 否则返回 false
- preOrderTraverse(cb):先序遍历或称前序遍历
- inOrderTraverse(cb):中序遍历
- postOrderTraverse(cb):后序遍历
- minNodeValue():最小节点值
- maxNodeValue():最大节点值
- removeNode(value):移除节点
- destory():销毁节点
二叉搜索树查找节点
在 JavaScript 中我们可以通过 hasOwnProperty 来检测指定 key 在对象是否存在,现在我们在二叉搜索中实现一个类似的方法,传入一个值 value 判断是否在二叉搜索树中存在
同样声明一个 SEARCH_RECUSIVE 辅助函数实现递归搜索查找
- 行 {1} 先判断传入的 node 是否为 null,如果为 null 就表示查找失败,返回 false。
- 行 {2} 说明已经找到了节点,返回 true。
- 行 {3} 表示要找的节点,比当前节点小,在左侧节点继续查找。
- 行 {4} 表示要找的节点,比当前节点大,在右侧节点继续查找。
/**
* 递归搜索
* @param { Object } node
* @param { Number } value
*/
[SEARCH_RECUSIVE](node, value) {
if (node === null) { // {1} 节点为 null
return false;
} else if (value === node.value) { // {2} 找到节点
return true;
} else if (value < node.value) { // {3} 从左侧节点搜索
return this[SEARCH_RECUSIVE](node.left, value);
} else { // {4} 从右侧节点搜索
return this[SEARCH_RECUSIVE](node.right, value);
}
}
四,找出这个数组中出现次数最多的一项及这一项出现了多少次
const arr = [1, 2, 1, 2, "1", "1", "2", "2", 1, "2", "2", 4, 5, 6];
function aaa(arr) {
let max,maxNum;
let b = new Map();
arr.forEach(i => {
let val = b.get(i)
if (b.has(i)) {
b.set(i, ++val)
} else {
b.set(i,1)
}
});
console.log(b);
maxNum = Math.max(...b.values())
console.log(maxNum);
for (const key of b.keys()) {
if (b.get(key) === maxNum) {
max = key
}
}
console.log(max);
return { max: max, maxNum: maxNum };
}
aaa(arr);
五,说一下instanceof的原理,实现一下
function instance_of(a,b) {
let atype = Object.getPrototypeOf(a);
while (true) {
if(atype == null) return false
if(atype == b.prototype){
return true
}
atype = Object.getPrototypeOf(atype);
}
}
六,知道map方法吗?实现一下。
首先我们来看一下map方法的使用以及具体的参数,currentValue 必须。当前元素的值
var arr = ["a","b","c","d","e"];
arr.map(function(currentValue,index,arr){
console.log("当前元素"+currentValue)
console.log("当前索引"+index)
console.log("数组对象"+arr)
})
Array.prototype.newMap = function(fn) {
var newArr = [];
for(var i = 0; i<this.length; i++){
newArr.push(fn(this[i],i,this))
}
return newArr;
}
七,实现ajax,至少实现get和post方法。这里深挖了get和post具体的传参方式以及ajax中具体是如何实现的
//get
xhr = new XMLHttpRequest();//标准
//open()的三个参数,(1)请求方式(get或post),(2)请求地址,(3)同步或者异步标志位,默认是true表示异步,false表示同步
xhr.open('get','url',true);
xhr.send(null);//get请求这里需要添加null参数,post请求为所传参数
指定回调函数:就是接收服务器响应的数据函数
xhr.onreadystatechange = function(){
//onreadystatechange:为状态改变的事件触发器,每个状态改变时都会触发这个事件处理器,通常会调用一个JavaScript函数
if(xhr.readyState == 4){
//readyState:为请求的状态。有5个可取值:0 = 未初始化,1 = 正在加载,2 = 已加载,3 = 交互中,4 = 完成
if(xhr.status == 200){
//服务器的HTTP状态码,如:404 = "文件末找到" 、200 ="成功" ,等等
alert(xhr.responseText);
}
}
}
//post
var param = 'username='+uname+"&type=post";
xhr.open('post','01ajax.php',true);
xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
xhr.send(param);//post请求参数在这里传递,并且不需要转码