用setTimeout 实现 setInterval (带清除定时器)
let time = 0;
let inter = setMyInter(()=>{
time++;
console.log(time)
},1000)
setTimeout(() => {
inter.cancel();
}, 10000);
function setMyInter(fn,timeout){
let time = null;
function myInterval(){
fn();
time = setTimeout(()=>{
myInterval();
},timeout);
}
myInterval();
return {
cancel:()=>{
clearTimeout(time);
}
}
}
//增加执行方法入参的版本
let time = 0;
let inter = setMyInter((...val)=>{
time++;
console.log(val +" === " +time)
},1000,"haha","hehe")
setTimeout(() => {
console.log('==finish==')
inter.cancel();
}, 5000);
function setMyInter(fn,timeout,...args){
let time = null;
function myInterval(){
let curArgs = Array.prototype.slice.call(arguments);
console.log("1111=",curArgs);
fn.apply(this,curArgs);
time = setTimeout(()=>{
myInterval.apply(this,curArgs);
},timeout);
}
console.log("1111=",args);
myInterval.apply(this,args);
return {
cancel:()=>{
clearTimeout(time);
}
}
}
setInterval缺陷
1.setInterval对自己调用的代码是否报错漠不关心。即使调用的代码报错了,它依然会持续的调用下去
2.setInterval无视网络延迟。在使用ajax轮询服务器是否有新数据时,必定会有一些人会使用setInterval,然而无论网络状况如何,它都会去一遍又一遍的发送请求,如果网络状况不良,一个请求发出,还没有返回结果,它会坚持不懈的继续发送请求,最后导致的结果就是请求堆积。
3.setInterval并不定时。如果它调用的代码执行的时间小于定时的时间,它会跳过调用,这就导致无法按照你需要的执行次数或无法得到你想要的结果。
数组去重
function uniqueArr(arr){
return [...new Set(arr)];
}
数组扁平化
let arr2 = [1,[2,3],4,5,[6,[7,8]],9]
arr2 = flatter(arr2);
console.log(arr2);
function flatter(arr){
let retArr = [];
arr.forEach(element => {
if(Array.isArray(element)){
retArr = retArr.concat(flatter(element));
}else{
retArr = retArr.concat(element);
}
});
return retArr;
}
手写call apply (bind有点复杂,先不写了...)
//apply 的所有参数都必须放在一个数组里面传进去
Function.prototype.myApply = function(context,args){
if(context == null){
context = window;
}
let fn = Symbol(); //创造唯一的key
context[fn] = this;//这里的this指的是当前的要执行的函数
return context[fn](args);//执行 -- 返回执行结果
}
//call 的参数是直接放进去的,第二第三第 n 个参数全都用逗号分隔 ...组装成数组 就和apply一样了
Function.prototype.myCall = function(context,...args){
if(context == null){
context = window;
}
let fn = Symbol(); //创造唯一的key
context[fn] = this;//这里的this指的是当前的要执行的函数
return context[fn](args);//执行(因为用的是context执行的 所以里面的上下文已经是context) -- 返回执行结果
}
深拷贝
function deepClone(obj){
if(obj == null || typeof obj !== 'object' ){
//不是引用类型 是值类型
return obj;
}
let result;
if(obj instanceof Array){ //或者用 Array.isArray(obj)
//是数组
result = [];
}else{
result = {};
}
for(let key in obj){
if(obj.hasOwnProperty(key)){
result[key] = deepClone(obj[key]);
}
}
return result;
}
koa洋葱模型
const middleware = []
let mw1 = async function (ctx, next) {
console.log("next前,第一个中间件")
await next()
console.log("next后,第一个中间件")
}
let mw2 = async function (ctx, next) {
console.log("next前,第二个中间件")
await next()
console.log("next后,第二个中间件")
}
let mw3 = async function (ctx, next) {
console.log("第三个中间件,没有next了")
}
function use(mw) {
middleware.push(mw)
}
use(mw1)
use(mw2)
use(mw3)
let fn = function (ctx) {
return dispatch(0)
function dispatch(i) {
let currentMW = middleware[i]
if(!currentMW) {
return
}
return currentMW(ctx, dispatch.bind(null, i + 1))
}
}
fn()
// output =>>>
// next前,第一个中间件
// next前,第二个中间件
// 第三个中间件,没有next了
// next后,第二个中间件
// next后,第一个中间件
curry
function curry (fn, currArgs) {
return function() {
let args = [].slice.call(arguments);
// 首次调用时,若未提供最后一个参数currArgs,则不用进行args的拼接
if (currArgs !== undefined) {
args = args.concat(currArgs);
}
// 递归调用 这里的fn.length表示的是fn 入参的个数
if (args.length < fn.length) {
return curry(fn, args);
}
// 递归出口
return fn.apply(null, args);
}
}
function sum(a, b, c) {
console.log(a + b + c);
}
const fn = curry(sum);
fn(1, 2, 3); // 6
fn(1, 2)(3); // 6
fn(1)(2, 3); // 6
fn(1)(2)(3); // 6
防抖
let myinput = document.getElementById('myinput');
myinput.addEventListener('keyup',debounce(function(){
console.log(myinput.value);
},500));
function debounce(fn , delay = 100){
let timer = null;
return function(){
let context = this;
if(timer){
clearTimeout(timer);
}
timer = setTimeout(function() {
fn.apply(context,arguments);
timer = null;
}, delay);
}
}
节流
let drag = document.getElementById('drag');
drag.addEventListener('drag',throtte(function(e){
console.log(e.offsetX,e.offsetY)
}),500);
function throtte(fn,delay = 100){
let timer = null;
return function(){
let context = this;
if(timer){
return;
}
timer = setTimeout(() => {
fn.apply(context,arguments);
timer = null;
}, delay);
}
}