专栏首页IMWeb前端团队撩一下一些必要的js工具函数

撩一下一些必要的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工具函数

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

    IMWeb前端团队
  • 教你做一个异步的fis3插件

    本文作者:IMWeb 黄龙 原文出处:IMWeb社区 未经同意,禁止转载 不清楚fis3是什么的可以先看这个链接 http://fis.baidu.c...

    IMWeb前端团队
  • 教你做一个异步的fis3插件

    从fis的官方文档上看,fis 除了deploy 插件是支持异步的其它都不支持。但是有好多node包 都是异步,怎么才能让fis支持异步插件呢?

    IMWeb前端团队
  • 撩一下一些必要的js工具函数

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

    IMWeb前端团队
  • DOM操作(20171027)

    天天_哥
  • JavaScript 判断输入的值为数字

    使用js自带全局函数isNaN(), isNaN()返回一个Boolean值,如下 :

    Devops海洋的渔夫
  • [JavaScript]自执行函数

    最近在接触mui的时候,遇到了一段代码: 1 (function($, doc) { 2 $.init({ 3 ...

    CN_Simo
  • createEventObject 与 createEvent EDIT WATCH

    jQuery中有很好用的trigger来触发事件,但总不能写什么都去引入jQuery吧

    meteoric
  • 关于Java代码优化的N条建议!

    本文是作者:五月的仓颉 结合自己的工作和平时学习的体验重新谈一下为什么要进行代码优化。在修改之前,作者的说法是这样的:

    Java后端技术
  • 原 Promise 实现

    魂祭心

扫码关注云+社区

领取腾讯云代金券