JS常见算法

90 阅读2分钟

一、求一个字符串出现的次数

function queryStr(str){
    let json = {};
    let max = 0;
    let msg = "";
    for(let i = 0;i<str.length;i++){
        if(!json[str.charAt(i)]) {
            json[str.charAt(i)] = 1;
        } else {
            json[str.charAt(i)]++;
        }
    }
    // 循环json对象
    for(let i in json) {
        if(json[i]>max){
            max = json[i];
            msg = i;
        }
    }
    return {
    max,msg
    }
}
console.log(
    "出现字数最多的字符是:",
    queryStr("hello").msg,
    "出现次数为:"
    queryStr("hello").max
)

二、判断一个对象是否为数组

  • 使用Array.isArray判断,如果返回true,说明是数组
  • 使用instanceof Array判断,如果返回true,说明是数组
  • 使用Object.prototype.toString.call()判断
    function isArray(arg) {
        if(typeof arg === "object") {
            return Object.prototype.toString.call(arg) === "[Object Array]"
        }
        return false
    }

Object对象和它的原型链上各自有一个toString()方法,第一个返回的是一个函数,第二个返回的是值类型。

通过callArraythis上下文切换到Object,从而调用了Object.prototype.toString(),因此返回[object Array]

三、监听函数

function on(elem,type,selector,fn) {
    if(fn == null) {
        fn = selector;
        selector = null
    }
    elem.addEventListener(type,function(e){
        const target = e.target;
        if(selector){
            if(target.matches(selector)) {
                fn.call(target.e);
            }
        } else {
            fn(e)
        }
    })
}

四、手写简易的ajax

function ajax(url) {
    const p = newPromise((resolve,reject) => {
        const xhr = new XMLHttpRequest();
        xhr.open("GET",url);
        xhr.onreadystatechange=function(){
            if(xhr.readyState === 4) {
                if(xhr.status=== 200) {
                    resolve(JSON.parse(xhr.responseText));
                } else if(xhr.status === 400) {
                    reject(new Error("404 not found"));
                }
            }
        }
        xhr.send(null)
    })
    return p;
}
const url="/data/test.json";
ajax(url).then((res) => console.log(res))
.catch((err)=>console.error(err));

五、节流防抖

函数防抖

 在事件被触发n秒后再执行回调,如果在这n秒内有被触发,则重新计时

没有防抖的input

function ajax(content) {
    console.log('ajax request' + content)
}
let inputa = document.getElementById('unDebounce')
inputa.addEventListener('keyup'function(e){
    ajax(e.target.value)
})

加入防抖后的input

function ajax(content) {
    console.log('ajax request' + content)
}
function debounce(fun,delay){
    return function(args) {
        let that = this;
        let _args = args;
        clearTimeout(fun.id)
        fun.id = setTimeout(function() {
            fun.call(that,_args)
        },delay)
    }
}
let inputb = document.getElementById('debounce')
let debounceAjax = debounce(ajax,500)
inputb.addEventListener('keyup',function(e) {
    debounceAjax(e.target.value)
})

函数节流

规定在一个单位时间内,只能触发一次函数。如果这个单位时间内触发多次函数,只有一次生效
function throttle(fun,delay) {
    let last,deferTimer;
    return function(args) {
        let that = this;
        let _args = arguments;
        let now = +new Date()
        if(last && now<last + delay) {
            clearTimeout(deferTimer)
            deferTimer = setTimeout(function() {
                last = now;
                fun.apply(that,_args)
            },delay)
        } else {
            last = now
            fun.apply(that,_args)
        }
    }
}
let throttleAjax = throttle(ajax,1000)
let inputc = document.getElementById('throttle')
inputc.addEventListener('keyup', function(e){
    throttleAjax(e.target.value)
})

在不断输入时,ajax会按照我们设定的时间,每1s执行一次 结合应用场景

debounce

1.   search搜索联想,用户在不断输入值时,用防抖来节约请求资源
2.   window触发resize的时候,不断的调整浏览器窗口大小会不断的触发这个事件,用防抖来让其只触发一次

throttle

1.鼠标不断点击触发,mousedown(单位时间内志触发一次)
2.监听滚动事件,比如是否滑到底部自动加载更多,用throttle来判断

六、对嵌套的数组进行扁平化

必须考虑到不同层级的嵌套

ex:stream([1,[2],[3,[4]]])应该返回[1,2,3,4]

1.在for循环中使用递归

function stream(arr) {
    var newArr = [];
    for(var i = 0;i<arr.length;i++) {
        if(!Array.isArra(arr[i])){
            newArr.push(arr[i]);
        } else {
            newArr = newArr.concat(stream(arr[i]));
        }
    }
    return newArr;
}

2.some()方法用于检测数组中的元素是否满足指定条件,会依次执行数组的每个元素

function flatten(arr) {
    while(arr.some(item => Array.isArray(item))){
        arr = [].concat(...arr)
    }
    return arr;
}
  • some()不会对空数组进行检测
  • some()不会改变原始数组 3.es6新增的数组实例方法flat() 4.如果数组中都是字符串,可以利用数组toString()方法