一些‘因吹斯汀’的JS代码整理

Author Avatar
Crown 7月 20, 2017
  • 在其它设备中阅读本文章

这里我会总结并收集一些我经常使用到的 JS 方法,以及我做的一些二次封装之类的函数,如有不对之处或者更好的建议,欢迎指正!!!

控制函数的触发频率

throttle( 节流 )debounce( 防抖 ) 是解决请求和响应速度不匹配问题的两个方案。区别如下:

  • throttle:输入参数如下,func被触发后会马上开始执行,但在wait时间内不会重复执行第二次。
/**
 * 频率控制 函数连续调用时,func 执行频率限定为 1 次 / time
 *
 * @param  {function}   fn      传入函数
 * @param  {number}     time      表示时间窗口的间隔
 * @return {function}             返回调用函数
 */
export function throttle(fn, time) {
    let _self = fn,
        timer,
        firstTime = true

    return function() {
        let args = arguments,
            _me = this

        if (firstTime) {
            _self.apply(_me, args)
            return (firstTime = false)
        }

        if (timer) {
            return false
        }

        timer = setTimeout(function() {
            clearTimeout(timer)
            timer = null
            _self.apply(_me, args)
        }, time || 500)
    }
}
  • debounce:输入参数如下,func会在不间断的相同事件触发停止wait时间后开始执行,事件如果一直在触发就一直不会往下执行。
/**
 * 空闲控制 函数连续调用时,空闲时间必须大于或等于 wait,func 才会执行
 *
 * @param  {function} fn        传入函数
 * @param  {number}   wait        表示时间窗口的间隔
 * @return {function}             返回客户调用函数
 */
export function debounce(fn, wait) {
    var timer = null
    return function() {
        clearTimeout(timer)
        timer = setTimeout(() => {
            fn()
        }, wait)
    }
}

这里我贴下简单的使用以及功能介绍。

//函数会在你开始修改浏览器尺寸1秒后执行,在此期间里不断修改尺寸也只会触发一次。
var throttle = throttle(function() {
    console.log(1)
}, 1000)
window.add

//函数会在你停止修改浏览器尺寸1秒后时才执行,在这之前,你的不断修改尺寸行为会不断将改计时清零。
var debounce = debounce(function() {
    console.log(2)
}, 1000)
$(window).resize(debounce)

事件代理

eventDelegate('#list', 'li', 'click', function() {
    console.log(this)
})

function eventDelegate(parentSelector, targetSelector, events, foo) {
    // 触发执行的函数
    function triFunction(e) {
        // 兼容性处理
        var event = e || window.event
        // 获取到目标阶段指向的元素
        var target = event.target || event.srcElement
        // 获取到代理事件的函数
        var currentTarget = event.currentTarget
        // 处理 matches 的兼容性
        if (!Element.prototype.matches) {
            Element.prototype.matches =
                Element.prototype.matchesSelector ||
                Element.prototype.mozMatchesSelector ||
                Element.prototype.msMatchesSelector ||
                Element.prototype.oMatchesSelector ||
                Element.prototype.webkitMatchesSelector ||
                function(s) {
                    var matches = (this.document || this.ownerDocument).querySelectorAll(s),
                        i = matches.length
                    while (--i >= 0 && matches.item(i) !== this) {}
                    return i > -1
                }
        }
        // 遍历外层并且匹配
        while (target !== currentTarget) {
            // 判断是否匹配到我们所需要的元素上
            if (target.matches(targetSelector)) {
                var sTarget = target
                // 执行绑定的函数,注意 this
                foo.call(sTarget, Array.prototype.slice.call(arguments))
            }
            target = target.parentNode
        }
    }
    // 如果有多个事件的话需要全部一一绑定事件
    events.split('.').forEach(function(evt) {
        // 多个父层元素的话也需要一一绑定
        Array.prototype.slice.call(document.querySelectorAll(parentSelector)).forEach(function($p) {
            $p.addEventListener(evt, triFunction)
        })
    })
}

函数记忆 , 判断是不是质数 .

// 方法一:
function isPrime1(n) {
    if (n <= 3) {
        return true
    } else {
        for (var i = 2; i < Math.sqrt(n); i++) {
            if (n % i == 0) {
                return false
            }
        }
        return true
    }
}
// 方法二: hash
var isPrime2 = (function() {
    //hash
    var hash = {}
    return function(n) {
        if (n <= 3) {
            return true
        } else if (hash[n] !== undefined) {
            return hash[n]
        } else {
            for (var i = 2; i < Math.sqrt(n); i++) {
                if (n % i == 0) {
                    return (hash[n] = false)
                }
            }
            return (hash[n] = true)
        }
    }
})()

数组去重

// 方法一:
var arr1 = [1, 2, 3, 2, 1, 2]

function repeat1(arr) {
    for (var i = 0, arr2 = []; i < arr.length; i++) {
        if (arr2.indexOf(arr[i]) == -1) {
            arr2.push(arr[i])
        }
    } //(遍历结束)
    return arr2
}
// 方法二:hash
function repeat2(arr) {
    //遍历arr中每个元素,同时声明hash
    for (var i = 0, hash = {}; i < arr.length; i++) {
        //hash中是否包含当前元素值的建
        //如果不包含,就hash添加一个新元素,以当前元素值为key,value默认为1
        if (hash[arr[i]] === undefined) {
            hash[arr[i]] = 1
        }
    } //(遍历结束)
    //将hash转为索引:
    var i = 0
    var arr2 = []
    for (arr2[i++] in hash);
    return arr2
}
// 方法三:
function repeat3(arr) {
    return arr
        .sort()
        .join(',,')
        .replace(/(^|,,)([^,]+)(,,\2)*/g, '$1$2')
        .split(',,')
}
console.log(repeat3(arr1))

统计字符串中每种字符出现的次数 , 出现次数最多的是 ? 出现 ? 次

var str = 'helloworld'
// 方法一:用hash
for (var i = 0, hash = {}; i < str.length; i++) {
    if (hash[str[i]]) {
        hash[str[i]]++
    } else {
        hash[str[i]] = 1
    }
}
console.dir(hash)
// 方法二:用正则
var arr = str
    .split('')
    .sort()
    .join('')
    .match(/([a-z])\1*/g)
    .sort(function(a, b) {
        return b.length - a.length
    })
console.log('出现最多的是: ' + arr[0][0] + '共' + arr[0].length + '次')
var hash = {}
arr.forEach(function(val) {
    hash[val[0]] = val.length
})
console.dir(hash)

函数 currying( 柯里华 )

var getN

function add(n) {
    getN = function() {
        console.log(n)
    }
    return function(m) {
        n += m
        arguments.callee.toString = function() {
            return n
        }
        return arguments.callee
    }
}
add(1)(2)(3)
getN() //6
add(1)(2)(3)(4)
getN() //10
alert(add(1)(2)(3)) //6
alert(add(1)(2)(3)(4)) //10

比较简单的页面状态管理

// 自执行创建模块
;(function() {
    // states 结构预览
    // states = {
    //     a: 1,
    //     b: 2,
    //     m: 30,
    //     o: {}
    // }
    var states = {} // 私有变量,用来存储状态与数据

    // 判断数据类型
    function type(elem) {
        if (elem == null) {
            return elem + ''
        }
        return toString
            .call(elem)
            .replace(/[\[\]]/g, '')
            .split(' ')[1]
            .toLowerCase()
    }

    /**
     * @Param name 属性名
     * @Description 通过属性名获取保存在states中的值
     */
    function get(name) {
        return states[name] ? states[name] : ''
    }

    function getStates() {
        return states
    }

    /*
    * @param options {object} 键值对
    * @param target {object} 属性值为对象的属性,只在函数实现时递归中传入
    * @desc 通过传入键值对的方式修改state树,使用方式与小程序的data或者react中的setStates类似
    */
    function set(options, target) {
        var keys = Object.keys(options)
        var o = target ? target : states

        keys.map(function(item) {
            if (typeof o[item] == 'undefined') {
                o[item] = options[item]
            } else {
                type(o[item]) == 'object' ? set(options[item], o[item]) : (o[item] = options[item])
            }
            return item
        })
    }

    // 对外提供接口
    window.get = get
    window.set = set
    window.getStates = getStates
})()

// 具体使用如下

set({ a: 20 }) // 保存 属性a
set({ b: 100 }) // 保存属性b
set({ c: 10 }) // 保存属性c

// 保存属性o, 它的值为一个对象
set({
    o: {
        m: 10,
        n: 20
    }
})

// 修改对象o 的m值
set({
    o: {
        m: 1000
    }
})

// 给对象o中增加一个c属性
set({
    o: {
        c: 100
    }
})
console.log(getStates())

该方法参考出处


随着我自己个人的技术水平的提高,我也会尽最大力量去原创一些有价值有内容的文章出来。在此期间我的文章会同步更新在以下地方 , 欢迎大家在自己长逛的网站中关注或者star我的 Github 来了解我的最新消息 !!!

未经允许 , 不准转载