撩一下一些必要的js工具函数

不管是什么项目,总有一些基本的功能函数默默的躺在你的工具库中,为你遮挡bug,提升性能,一起来复习下!

debounce

当监听一些scroll,resize事件时,如果我们什么都不限制,srcoll事件在滚动过程中会一直触发,极大的影响性能,这个时候,就需要节流函数debounce。debounce函数返回一个函数,在给定的时间间隔下,连续被调用将不会触发。

/* 事件停止被触发N秒后才会再次触发回调
 * @param {Function} func - 回调执行函数
 * @param {String} wait - 触发间隔
 * @param {Boolean} immediate - 是否延时执行
 */
function debounce(func, wait, immediate) {
    var timeout;
    return function() {
        var context = this, args = arguments;
        var later = function() {
            timeout = null;
            if (!immediate) func.apply(context, args);
        };
        var callNow = immediate && !timeout;
        clearTimeout(timeout);
        timeout = setTimeout(later, wait);
        if (callNow) func.apply(context, args);
    };
};

// Usage
var myEfficientFn = debounce(function() {
    // todo
}, 250);
window.addEventListener('resize', myEfficientFn);

poll

很多时候,我们需要了解某个函数的执行状态,并根据状态执行相应的处理。在没有事件通知时,需要以一定的时间间隔轮询执行状态。

/* 轮询条件函数,根据状态执行相应回调
 * @param {Function} fn- 条件函数
 * @param {Function} callback - 成功回调
 * @param {Function} errback - 失败回调
 * @param {int} timeout - 超时间隔
 * @param {int} interval - 轮询间隔
 */
function poll(fn, callback, errback, timeout, interval) {
    var endTime = Number(new Date()) + (timeout || 2000);
    interval = interval || 100;

    (function p() {
            // If the condition is met, we're done! 
            if(fn()) {
                callback();
            }
            // If the condition isn't met but the timeout hasn't elapsed, go again
            else if (Number(new Date()) < endTime) {
                setTimeout(p, interval);
            }
            // Didn't match and too much time, reject!
            else {
                errback(new Error('timed out for ' + fn + ': ' + arguments));
            }
    })();
}

// Usage:  ensure element is visible
poll(
    function() {
        return document.getElementById('lightbox').offsetWidth > 0;
    },
    function() {
        // Done, success callback
    },
    function() {
        // Error, failure callback
    }
);

once

实用的执行一次函数,不用多解释。虽然很简单的函数,但是防止重复加载或者初始化的习惯必须养成。

function once(fn, context) { 
    var result;

    return function() { 
        if(fn) {
            result = fn.apply(context || this, arguments);
            fn = null;
        }

        return result;
    };
}

// Usage
var canOnlyFireOnce = once(function() {
    console.log('Fired!');
});

getAbsoluteUrl

从字符串变量中获取绝对url路径并没有那么容易,URL构造函数必须提供必要的参数,getAbsoluteUrl函数可以单纯的从字符串输入中得到绝对路径。

var getAbsoluteUrl = (function() {
    var a;

    return function(url) {
        if(!a) a = document.createElement('a');
        a.href = url;

        return a.href;
    };
})();

// Usage
getAbsoluteUrl('/shirlyzhang');  // "http://imweb.io/shirlyzhang"

isNative

当需要重写某个函数时,必须先确定其是否是原生函数。

(function() {
  var toString = Object.prototype.toString;
  var fnToString = Function.prototype.toString;
  // 构造函数,数组
  var reHostCtor = /^\[object .+?Constructor\]$/;

  var reNative = RegExp('^' +
    // 强制转换(Object-toString)为字符串
    String(toString)
    // 转移特殊字符
    .replace(/[.*+?^${}()|[\]\/\\]/g, '\\$&')
    // 替换 `toString` 为 `.*?`, 保持模板通用
    // 替换 `for ...` 等字符来支持添加了额外信息的环境
    .replace(/toString|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$'
  );

  function isNative(value) {
    var type = typeof value;
    return type == 'function'
      // 使用 `Function#toString` 来绕过value原生的 `toString` 方法,避免误判
      ? reNative.test(fnToString.call(value))
      // 回退到宿主对象检查。因为某些环境中,会将类型数组当做DOM方法。
      : (value && type == 'object' && reHostCtor.test(toString.call(value))) || false;
  }

  module.exports = isNative;
}());

// Usage
isNative(alert); // true
isNative(myCustomFunction); // false

insertRule

使用css选择器来选取节点修改样式不太高效,可以选择用js新建一段css样式规则插入。

var sheet = (function() {
    var style = document.createElement('style');

    // WebKit 兼容
    style.appendChild(document.createTextNode(''));

    document.head.appendChild(style);
    return style.sheet;
})();

// Usage
sheet.insertRule("header { float: left; opacity: 0.8; }", 1);

matchesSelector

判断页面内的元素是否具有某些属性值。

function matchesSelector(el, selector) {
    var p = Element.prototype;
    var f = p.matches || p.webkitMatchesSelector || p.mozMatchesSelector || p.msMatchesSelector || function(s) {
        return [].indexOf.call(document.querySelectorAll(s), this) !== -1;
    };
    return f.call(el, selector);
}

// Usage
matchesSelector(document.getElementById('myDiv'), 'div.someSelector[some-attribute=true]')

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏王磊的博客

js节流函数和js防止重复提交的N种方法

应用情景 经典使用情景:js的一些事件,比如:onresize、scroll、mousemove、mousehover等; 还比如:手抖、手误、服务器没有响应之...

33212
来自专栏鸿的学习笔记

python源码阅读笔记之GC

441
来自专栏对角另一面

读Zepto源码之Event模块

Event 模块是 Zepto 必备的模块之一,由于对 Event Api 不太熟,Event 对象也比较复杂,所以乍一看 Event 模块的源码,有点懵,细看...

2190
来自专栏玩转JavaEE

MongoDB固定集合

一般情况下我们创建的集合是没有大小的,可以一直往里边添加文档,这种集合可以动态增长,MongoDB中还有一种集合叫做固定集合,这种集合的大小是固定的,我可以在创...

3197
来自专栏王磊的博客

js节流函数和js防止重复提交的N种方法

723
来自专栏Android知识点总结

来谈谈Java的深浅拷贝吧

834
来自专栏小白安全

XSS防御速查表

一、介绍 本文提供了一种通过使用输出转义/编码来防止XSS攻击的简单有效模型。尽管有着庞大数量的XSS攻击向量,依照下面这些简单的规则可以完全防止这种...

4536
来自专栏瓜大三哥

UVM(十)之config机制

UVM(十)之config机制 1 验证平台中要配置的众多的参数 在一个验证平台中,有众多的参数需要配置。如在mac_driver中,按照以太网相关协议的规定,...

2296
来自专栏Java帮帮-微信公众号-技术文章全总结

【选择题】Java基础测试题一(10道)

【选择题】Java基础测试题一(10道) 1.下面哪些是合法的变量名? (DEG) A.2variable //不能以数字开头 ...

3858
来自专栏Java帮帮-微信公众号-技术文章全总结

Java设计模式-组合模式

组合模式: 将对象组合成树形结构以表示‘部分-整体’的层次结构, 使得用户对单个对象和组合对象的使用具有一致性. 解析 组合模式描述了如何将容器和叶子节点进行...

3346

扫码关注云+社区