工具函数

String

contains

function contains (target, str, separator) {
    return separator ? (separator + target + separator).indexOf(separator + str + separator) > -1 : target.indexOf(str) > -1;
}

startsWith

function startsWith (target, str, ignorecase) {
    var start_str = target.substr(0, str.length);
    return ignorecase ? start_str.toLowerCase() === str.toLowerCase() : start_str === str;
}

endsWith

function endsWith (target, str, ignorecase) {
    var end_str = target.substring(target.length - str.length);
    return ignorecase ? end_str.toLowerCase() === str.toLowerCase() : end_str === str;
}

repeat

function repeat (target, n) {
    var s = target,
        total = "";
    while (n > 0) {
        if (n % 2 == 1)
            total += s;
        if (n == 1)
            break;
        s += s;
        n = n >> 1;
    }
    return total;
}

byteLen

byteLen: 取得一个字符串所有字节的长度(来自腾讯的解决方案。腾讯通过多子域名+postMessage+manifest 离线 proxy 页面的 方式扩大 localStorage 的存储空间,在这过程中需要知道用户已经存了多少东西,因此,我们就 必须编写一个严谨的 byteLen 方法。)

/** *
* http://www.alloyteam.com/2013/12/js-calculate-the-number-of-bytes-occupied-by-a-str ing/
* 计算字符串所占的内存字节数,默认使用 UTF-8 的编码方式计算,也可制定为 UTF-16
* UTF-8 是一种可变长度的 Unicode 编码格式,使用 1 至 4 个字节为每个字符编码 *
* 000000 - 00007F(128个代码)
* 000080 - 0007FF(1920个代码) 
* 000800 - 00D7FF 00E000 - 00FFFF(61440个代码) 0zzzzzzz(00-7F) 一个字节 110yyyyy(C0-DF) 10zzzzzz(80-BF) 两个字节 1110xxxx(E0-EF) 10yyyyyy 10zzzzzz 3个字节
* 010000 - 10FFFF(1048576 个代码) 11110www(F0-F7) 10xxxxxx 10yyyyyy 10zzzzzz 4 个字节 *
* 注: Unicode 在范围 D800-DFFF 中不存在任何字符
* {@link <a onclick="javascript:pageTracker._trackPageview('/outgoing/zh.wikipedia.org/wiki/UTF -8');"
* href="http://zh.wikipedia.org/wiki/UTF-8">http://zh.wikipedia.org/wiki/UTF-8</a>} *
* UTF-16 大部分使用两个字节编码,编码超出 65535 的使用 4 个字节
* 000000 - 00FFFF 两个字节
* 010000 - 10FFFF 4 个字节
* {@link <a onclick="javascript:pageTracker._trackPageview('/outgoing/zh.wikipedia.org/wiki/UTF-16');" 
* href="http://zh.wikipedia.org/wiki/UTF-16">http://zh.wikipedia.org/wiki/UTF-16</a>} * @param {String} str
* @param {String} charset utf-8, utf-16
* @return {Number}
*/
function byteLen(str, charset) {
    var total = 0,
        charCode,
        i,
        len;
    charset = charset ? charset.toLowerCase() : '';
    if (charset === 'utf-16' || charset === 'utf16') {
        for (i = 0, len = str.length; i < len; i++) {
            charCode = str.charCodeAt(i);
            if (charCode <= 0xffff) {
                total += 2;
            } else {
                total += 4;
            }
        }
    } else {
        for (i = 0, len = str.length; i < len; i++) {
            charCode = str.charCodeAt(i);
            if (charCode <= 0x007f) {
                total += 1;
            } else if (charCode <= 0x07ff) {
                total += 2;
            } else if (charCode <= 0xffff) {
                total += 3;
            } else {
                total += 4;
            }
        }
    }
    return total;
}

truncate

用于对字符串进行截断处理,当超过限定长度,默认添加三个点号。

function truncate (target, length, truncation) {
    length = length || 30;
    truncation = truncation === void(0) ? '...' : truncation;
    return target.length > length ? target.slice(0, length - truncation.length) + truncation : String(target);
}

camelize

转换为驼峰风格

function camelize (target) {
    if (target.indexOf('-') < 0 && target.indexOf('_') < 0) {
        return target; //提前判断,提高getStyle等的效率
    }
    return target.replace(/[-_][^-_]/g, function(match) {
        return match.charAt(1).toUpperCase();
    });
}

underscored

转换为下划线风格

function underscored (target) {
    return target.replace(/([a-z\d])([A-Z])/g, '$1_$2').
    replace(/\-/g, '_').toLowerCase();
}

dasherize

function dasherize (target) {
    return underscored(target).replace(/_/g, '-');
}

capitalize

首字母大写

function capitalize(target) {
    return target.charAt(0).toUpperCase() + target.substring(1).toLowerCase();
}

stripTags

移除字符串中的 html 标签,但这方法有缺陷,如里面有 script 标签,会把这 些不该显示出来的脚本也显示出来。在 Prototype.js 中,它与 strip、stripScripts 是一组方法。

function stripTags (target) {
    return String(target || "").replace(/<[^>]+>/g, '');
}

stripScripts

移除字符串中所有的 script 标签。弥补 stripTags 方法的缺陷。此方法应 在 stripTags 之前调用。

function stripScripts (target) {
    return String(target || "").replace(/<script[^>]*>([\S\s]*?)<\/script>/img, '')
}

escapeHTML

将字符串经过 html 转义得到适合在页面中显示的内容,如将<替换 为 <。

function escapeHTML (target) {
    return target.replace(/&/g, '&amp;')
        .replace(/</g, '&lt;')
        .replace(/>/g, '&gt;')
        .replace(/"/g, "&quot;")
        .replace(/'/g, "&#39;");
}

unescapeHTML

将字符串中的 html 实体字符还原为对应字符。

function escapeHTML (target) {
    return target.replace(/&/g, '&amp;')
        .replace(/</g, '&lt;')
        .replace(/>/g, '&gt;')
        .replace(/"/g, "&quot;")
        .replace(/'/g, "&#39;"); //IE下不支持&apos;(单引号)转义
}

escapeRegExp

function escapeRegExp (target) {
    return target.replace(/([-.*+?^${}()|[\]\/\\])/g, '\\$1');
}

trim

// 简洁
function trim (str) {
    return str.replace(/^\s+|\s+$/g, '');
}
function trim (string) {
    // uFEFF:字节顺序标记(英语:byte-order mark,BOM)是位于码点U+FEFF的统一码字符的名称。当以UTF-16或UTF-32来将UCS/统一码字符所组成的字符串编码时,这个字符被用来标示其字节序。它常被用来当做标示文件是以UTF-8、UTF-16或UTF-32编码的记号。
    return (string || '').replace(/^[\s\uFEFF]+|[\s\uFEFF]+$/g, '');
};
// 速度快
function trim (str) {
    var whitespace = ' \n\r\t\f\x0b\xa0\u2000\u2001\u2002\u2003\n\
\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u200b\u2028\u2029\u3000';
    for (var i = 0; i < str.length; i++) {
        if (whitespace.indexOf(str.charAt(i)) === -1) {
            str = str.substring(i);
            break;
        }
    }
    for (i = str.length - 1; i >= 0; i--) {
        if (whitespace.indexOf(str.charAt(i)) === -1) {
            str = str.substring(0, i + 1);
            break;
        }
    }
    return whitespace.indexOf(str.charAt(0)) === -1 ? str : '';
}

pad

与 trim 相反,pad 可以为字符串的某一端添加字符串。

function pad (target, n, filling, right, radix) {
    var num = target.toString(radix || 10);
    filling = filling || "0";
    while (num.length < n) {
        if (!right) {
            num = filling + num;
        } else {
            num += filling;
        }
    }
    return num;
}

wbr

为目标字符串添加 wbr 软换行。不过需要注意的是,它并不是在每个字符之后都 插入字样,而是相当于在组成文本节点的部分中的每个字符后插入字样。如 aabbcc,返回 aabbcc。另外, 在 Opera 下,浏览器默认 css 不会为 wbr 加上样式,导致没有换行效果,可以在 css 中加上 wbr: after { content: "\00200B" } 解决此问题。

function wbr (target) {
    return String(target).replace(/(?:<[^>]+>)|(?:&#?[0-9a-z]{2,6};)|(.{1})/gi, '$&<wbr>').replace(/><wbr>/g, '>');
}

!> 注:IE仅6-7兼容此标签 https://caniuse.com/#search=wbr

format

轻量字符串模版

function format (str, object) {
    var array = Array.prototype.slice.call(arguments, 1);
    return str.replace(/\\?\#{([^{}]+)\}/gm, function(match, name) {
        if (match.charAt(0) == '\\')
            return match.slice(1);
        var index = Number(name)
        if (index >= 0)
            return array[index];
        if (object && object[name] !== void 0)
            return object[name];
        return '';
    });
}

Example:

var a = format("Result is #{0},#{1}", 22, 33);
console.log(a); //"Result is 22,33"
var b = format("#{name} is a #{sex}", {
    name: "Jhon",
    sex: "man"
});
console.log(b); //"Jhon is a man"

quote

在字符串两端添加双引号,然后内部需要转义的地方都要转义,用于接装 JSON 的键名或模析系统中。

// 原生方法,需要浏览器支持原生JSON
JSON.stringify
//http://code.google.com/p/jquery-json/
var escapeable = /["\\\x00-\x1f\x7f-\x9f]/g,
    meta = {
        '\b': '\\b',
        '\t': '\\t',
        '\n': '\\n',
        '\f': '\\f',
        '\r': '\\r',
        '"': '\\"',
        '\\': '\\\\'
    };

function quote (target) {
    if (target.match(escapeable)) {
        return '"' + target.replace(escapeable, function(a) {
            var c = meta[a];
            if (typeof c === 'string') {
                return c;
            }
            return '\\u' + ('0000' + c.charCodeAt(0).toString(16)).slice(-4)
        }) + '"';
    }
    return '"' + target + '"';
}
//https://github.com/ecomfe/etpl/blob/2.1.0/src/main.js#L207 
function stringLiteralize (source) {
    return '"' +
        source
        .replace(/\x5C/g, '\\\\')
        .replace(/"/g, '\\"')
        .replace(/\x0A/g, '\\n')
        .replace(/\x09/g, '\\t')
        .replace(/\x0D/g, '\\r') + '"';
}

Array

数组元素交换位置

/**
* 数组元素交换位置
* @param {array} arr 数组
* @param {number} index1 添加项目的位置
* @param {number} index2 删除项目的位置
* index1和index2分别是两个数组的索引值,即是两个要交换元素位置的索引值,如1,5就是数组中下标为1和5的两个元素交换位置
*/
function swapItem (arr, index1, index2) {
    arr[index1] = arr.splice(index2, 1, arr[index1])[0];
    return arr;
}

Object

get

用法同lodash的get

function get (object, path, defaultValue) {
    return (!Array.isArray(path) ? path.replace(/\[/g, '.').replace(/\]/g, '').split('.') : path)
            .reduce((obj, key) => (obj || {})[key], object) || defaultValue;
}

toQueryString

const toQueryString = obj => Object.keys(obj).map(key => `${encodeURIComponent(key)}=${encodeURIComponent(obj[key])}`).join('&');

Number

splitBit

千分位分割

function splitBit (num) {
    var c = (num.toString().indexOf ('.') !== -1) ? num.toLocaleString() : num.toString().replace(/(\d)(?=(?:\d{3})+$)/g, '$1,');
    return c;
}

Function

throttle

节流函数
应用场景:多数在监听页面元素滚动事件的时候会用到。因为滚动事件,是一个高频触发的事件。

function throttle (func, wait, options) {
  var timeout = void 0,
      context = void 0,
      args = void 0,
      result = void 0;
  var previous = 0;
  if (!options) options = {};

  var later = function later() {
    previous = options.leading === false ? 0 : Date.now();
    timeout = null;
    result = func.apply(context, args);
    if (!timeout) context = args = null;
  };

  var throttled = function throttled() {
    var now = Date.now();
    if (!previous && options.leading === false) previous = now;
    var remaining = wait - (now - previous);
    context = this;
    args = arguments;
    if (remaining <= 0 || remaining > wait) {
      if (timeout) {
        clearTimeout(timeout);
        timeout = null;
      }
      previous = now;
      result = func.apply(context, args);
      if (!timeout) context = args = null;
    } else if (!timeout && options.trailing !== false) {
      timeout = setTimeout(later, remaining);
    }
    return result;
  };

  throttled.cancel = function () {
    clearTimeout(timeout);
    previous = 0;
    timeout = context = args = null;
  };

  return throttled;
}

debounce

防抖函数
应用场景:最常见的就是用户注册时候的手机号码验证和邮箱验证了。只有等用户输入完毕后,前端才需要检查格式是否正确,如果不正确,再弹出提示语。

function debounce (fn, context) {
  fn.tId && clearTimeout(fn.tId)
  fn.tId = setTimeout((() => {
    fn.call(context)
  }, 500)
}
function debounce(func, wait, immediate) {
  var timeout = void 0;
  return function () {
    var context = this,
        args = arguments;
    var later = function later() {
      timeout = null;
      if (!immediate) {
        func.apply(context, args);
      }
    };
    var callNow = immediate && !timeout;
    clearTimeout(timeout);
    timeout = setTimeout(later, wait);
    if (callNow) {
      func.apply(context, args);
    }
  };
}

Lang

isType

function isType (value, type) {
  return ({}).toString.call(value) === '[object ' + type + ']';
}

Dom

getStyle

function getStyle (dom, styleName) {
    if (!dom || !styleName) return null;
        styleName = camelize(styleName);
        if (styleName === 'float') {
            styleName = 'cssFloat';
        }
    /**
    * let style = window.getComputedStyle(dom, null);
    * 它等价于
    * let style = document.defaultView.getComputedStyle(dom, null);
    */
    return dom.currentStyle ? dom.currentStyle[styleName] : getComputedStyle(dom, null)[styleName]; // 火狐
}

getWidth

function getWidth (dom) {
    let stl = root.currentStyle || document.defaultView.getComputedStyle(dom);
    return ((dom.clientWidth || parseInt(stl.width, 10)) - parseInt(stl.paddingLeft, 10) - parseInt(stl.paddingRight, 10)).toFixed(0) - 0;
}

modifyCSS

function modifyCSS (dom, css) {
  if (dom) {
    for (var key in css) {
      if (css.hasOwnProperty(key)) {
        dom.style[key] = css[key];
      }
    }
  }
  return dom;
}

hasClass

function hasClass (el, cls) {
    if (!el || !cls) {return false;}
    if (cls.indexOf(' ') !== -1) {throw new Error('className should not contain space.');}
    if (el.classList) {
        return el.classList.contains(cls);
    } else {
        return (' ' + el.className + ' ').indexOf(' ' + cls + ' ') > -1;
    }
}

removeClass

function removeClass (el, cls) {
    if (!el || !cls) {return;}
    const classes = cls.split(' ');
    let curClass = ' ' + el.className + ' ';

    for (let i = 0, j = classes.length; i < j; i++) {
        const clsName = classes[i];
        if (!clsName) {continue;}

        if (el.classList) {
            el.classList.remove(clsName);
        } else {
            if (hasClass(el, clsName)) {
                curClass = curClass.replace(' ' + clsName + ' ', ' ');
            }
        }
    }
    if (!el.classList) {
        el.className = trim(curClass);
    }
}

addClass

/**
 * Created by linqiang on 2019/6/5.
 */
function addClass (el, cls) {
    if (!el) {return;}
    let curClass = el.className;
    const classes = (cls || '').split(' ');
    for (let i = 0, j = classes.length; i < j; i++) {
        const clsName = classes[i];
        if (!clsName) {continue;}
        if (el.classList) {
            el.classList.add(clsName);
        } else {
            if (!hasClass(el, clsName)) {
                curClass += ' ' + clsName;
            }
        }
    }
    if (!el.classList) {
        el.className = curClass;
    }
}

setOpacity

设置透明度

function setOpacity (elem, value) {
    elem.filters ? elem.style.filter = 'alpha(opacity=' + value + ')' : elem.style.opacity = value / 100;
}

getScrollTop

获得当前视口距离页面顶部的像素

function getScrollTop () {
    return document.documentElement.scrollTop || window.pageYOffset || document.body.scrollTop
}

getScrollLeft

获得当前视口距离页面左边的像素

function getScrollLeft () {
    return document.documentElement.scrollLeft || window.pageXOffset || document.body.scrollLeft
}

addEventListener

/**
 * 添加事件监听器
 * @param  {Object} target DOM对象
 * @param  {String} eventType 事件名
 * @param  {Funtion} callback 回调函数
 * @return {Object} 返回对象
 */
function addEventListener (target, eventType, callback) {
  if (target) {
    if (target.addEventListener) {
      target.addEventListener(eventType, callback, false);
      return {
        remove: function remove() {
          target.removeEventListener(eventType, callback, false);
        }
      };
    } else if (target.attachEvent) {
      target.attachEvent('on' + eventType, callback);
      return {
        remove: function remove() {
          target.detachEvent('on' + eventType, callback);
        }
      };
    }
  }
}

getKeyCode

document.onkeypress = function(e){  
    e = e || window.event;  
    console.log(e.keyCode || e.which);  // 常规浏览器 || IE  
}  

stopProp

阻止事件冒泡

function stopProp (event) {
    event = event || window.event;
    event.stopPropagation ? event.stopPropagation() : event.cancelBubble = true;  // 常规浏览器 || IE
};

preDef

阻止浏览器默认行为,如:按标签链接跳转

function preDef (event) {
    event = event || window.event
    event.preventDefault ? event.preventDefault() : event.returnValue = false // 常规浏览器 | IE
}

isIE6

IE6判定

function isIE6 () {
    //在IE6中[-1,].toString()为“1,”,‘-’会进行类型转换(转成数字类型),-"1,"  为NaN,所以返回!false 
    //非IE6   非IE6中[-1,].toString()为“1”,‘-’会进行类型转换(转成数字类型),-"1"  为-1,所以返回!true
    return !-[1,];
}

判定IE浏览器

function isIE () {
    //因为VB是微软发明的,其他浏览器无VBArray,至少可判定IE 6/7/8/9/10  
    return !!window.VBArray;
}
posted @ 2019-06-11 16:04  fanlinqiang  阅读(378)  评论(0编辑  收藏  举报