javascript实用代码片段

持续积累中~

拓展原型

Function.prototype.method = function (name, extend) {
  if (!this.prototype[name]) {
    this.prototype[name] = extend;
  }
  return this;
};

实现继承·方法 1

Function.method("inherits", function (Parent) {
  var _proptotype = Object.create(Parent.prototype);
  _proptotype.constructor = this.prototype.constructor;
  this.prototype = _proptotype;
  return this;
});

实现继承·方法 2

function inherits(child, parent) {
    var _proptotype = Object.create(parent.prototype);
    _proptotype.constructor = child.prototype.constructor;
    child.prototype = _proptotype;
    return {
        "child": child,
        "parent": parent
    };
}

实现继承·方法 3

//只创建临时构造函数一次
var inherit = (function () {
	var F = function () {};
	return function (C, P) {
		F.prototype = P.prototype;
		C.prototype = new F();
		C.uber = P.prototype;			// 存储超类
		C.prototype.constructor = C;	 // 重置构造函数指针
   }
})();

浅拷贝

function simpleCopy() {
    var c = {};
    for(var i in p) {
        c[i] = p[i];
    }
    return c;
}

深拷贝

export function deepCopy(obj, parent = null) {
    //parent用于递归循环引用爆栈处理
    // 创建一个新对象
    let result = new obj.constructor() //保持继承链
    let keys = Object.keys(obj),
        key = null,
        temp = null,
        _parent = parent
    // 该字段若有父级则需要追溯该字段的父级
    while (_parent) {
        // 如果该字段引用了它的父级则为循环引用
        if (_parent.originalParent === obj) {
            return _parent.currentParent // 循环引用直接返回同级的新对象
        }
        _parent = _parent.parent
    }
    for (let i = 0; i < keys.length; i++) {
        key = keys[i]
        temp = obj[key]
        if (temp && isType(temp) === 'date') {
            result[key] = new Date(temp)
            continue
        }
        if (temp && isType(temp) === 'regExp') {
            result[key] = new RegExp(temp)
            continue
        }
        // 若字段的值是一个对象/数组
        if (temp && (isType(temp) === 'object' || isType(temp) === 'array')) {
            // 递归执行深拷贝 将同级的待拷贝对象与新对象传递给 parent 方便追溯循环引用
            result[key] = deepCopy(temp, {
                originalParent: obj,
                currentParent: result,
                parent: parent
            })
        } else {
            result[key] = temp
        }
    }
    return result
}

带特性值的浅拷贝

function Composition(target, source){
    var desc = Object.getOwnPropertyDescriptor;
    var prop = Object.getOwnPropertyNames;
    var def_prop=Object.defineProperty;
    prop(source).forEach(function(key) {
        def_prop(target, key, desc(source, key))
    })
    return target;
}

mixin 混合

function mix() {
    var arg, prop, child = {};
	    for(arg = 0; arg < arguments.length; arg += 1) {
		    for(prop in arguments[arg]) {
			    if(arguments[arg].hasOwnProperty(prop)) {
				    child[prop] = arguments[arg][prop];
			    }
		    }
	    }
        return child;
}

对象拓展

var MYAPP = MYAPP || {};
MYAPP.namespace = function(ns_string) {
	var parts = ns_string.split('.'),
		parent = MYAPP,
		i;
	//忽略第一个
	if(parts[0] === "MYAPP") {
		parts = parts.slice(1);
	}
	for(i = 0; i < parts.length; i += 1) {
		//如果属性不存在,就创建
		if(typeof parent[parts[i]] === "undefined") {
			parent[parts[i]] = {};
		}
		parent = parent[parts[i]];
	}
	return parent;
};
MYAPP.namespace('once.upon.a.time.there.was.this.long.nested.property');

函数柯里化(Currying)

function curry(fn){
    var args = Array.prototype.slice.call(arguments, 1);
    return function(){
         var innerArgs = Array.prototype.slice.call(arguments);
         var finalArgs = args.concat(innerArgs);
         return fn.apply(null, finalArgs);
    };
}
function add(num1, num2){
    return num1 + num2;
}
var curriedAdd = curry(add, 5);
alert(curriedAdd(3)); //8

函数节流

function throttle(fn, wait){
	var timer;
	return function(...args){
      if(!timer){
          timer = setTimeout(()=>timer=null, wait);
          return fn.apply(this, args);
      }
	}
}

函数防抖

function debounce(fn, delay){
	var timer = null;
	return function(...args){
    	clearTimeout(timer);
    	timer = setTimeout(() => fn.apply(this, args), delay);
	}
}

跨文件共享私有对象(模块互访)

var blogModule = (function(my) {
    var _private = my._private = my._private || {},
    _seal = my._seal = my._seal || function() {
        delete my._private;
        delete my._seal;
        delete my._unseal;
    },
    _unseal = my._unseal = my._unseal || function() {
        my._private = _private;
        my._seal = _seal;
        my._unseal = _unseal;
    };
    return my;
}(obj || {}));

类型判断

export function isType(obj, type) {
    // tostring会返回对应不同的标签的构造函数
    const toString = Object.prototype.toString
    const map = {
        '[object Boolean]': 'boolean',
        '[object Number]': 'number',
        '[object String]': 'string',
        '[object Function]': 'function',
        '[object Array]': 'array',
        '[object Date]': 'date',
        '[object RegExp]': 'regExp',
        '[object Object]': 'object',
        '[object Undefined]': 'undefined',
        '[object Null]': 'null',
        '[object Error]': 'error',
    }
    if (obj instanceof HTMLElement) {
        return type ? type === 'element' : 'element'
    }
    return type ? type === map[toString.call(obj)] : map[toString.call(obj)]
}

软绑定[默认绑定可设置]

    Function.prototype.softBind = function(obj) {
        var fn = this;
        // 捕获所有 curried 参数
        var curried = [].slice.call( arguments, 1 );
        var bound = function() {
              return fn.apply(
                    (!this || this === (window || global)) ?
                         obj : this
                    curried.concat.apply( curried, arguments )
              );
        };
        bound.prototype = Object.create( fn.prototype );
        return bound;
    };

将时间戳转换成时间描述

function getTimeDesc(time) {
   var
    _n = 12 * 30 * 24 * 60 * 60 * 1000,
    _y = 30 * 24 * 60 * 60 * 1000,
    _d = 24 * 60 * 60 * 1000,
    _h = 60 * 60 * 1000,
    _m = 60 * 1000,
    _s = 1000,
    n, y, d, h, m, s, value;

    n = parseInt(time > _n ? time / _n : 0);
    n = n ? (n + '年') : '';
    time = time % _n;

    y = parseInt(time > _y ? time / _y : 0);
    y = y ? (y + '月') : '';
    time = time % _y;

    d = parseInt(time > _d ? time / _d : 0);
    d = d ? (d + '天') : '';
    time = time % _d;

    h = parseInt(time > _h ? time / _h : 0);
    h = h ? (h + '时') : '';
    time = time % _h;

    m = parseInt(time > _m ? time / _m : 0);
    m = m ? (m + '分') : '';
    time = time % _m;

    s = parseInt(time > _s ? time / _s : 0);
    s = s + '秒';

    value = n + y + d + h + m + s;
    console.log(value);
    return value;
}

toFixed 精度修复

  Number.prototype.toFixed = function (n) {
    if (n > 20 || n < 0) {
        throw new RangeError('toFixed() digits argument must be between 0 and 20');
    }
    const number = this;
    if (isNaN(number) || number >= Math.pow(10, 21)) {
        return number.toString();
    }
    if (typeof (n) == 'undefined' || n == 0) {
        return (Math.round(number)).toString();
    }

    let result = number.toString();
    const arr = result.split('.');

    // 整数的情况
    if (arr.length < 2) {
        result += '.';
        for (let i = 0; i < n; i += 1) {
            result += '0';
        }
        return result;
    }

    const integer = arr[0];
    const decimal = arr[1];
    if (decimal.length == n) {
        return result;
    }
    if (decimal.length < n) {
        for (let i = 0; i < n - decimal.length; i += 1) {
            result += '0';
        }
        return result;
    }
    result = integer + '.' + decimal.substr(0, n);
    const last = decimal.substr(n, 1);

    // 四舍五入,转换为整数再处理,避免浮点数精度的损失
    if (parseInt(last, 10) >= 5) {
        const x = Math.pow(10, n);
        result = (Math.round((parseFloat(result) * x)) + 1) / x;
        result = result.toFixed(n);
    }

    return result;
  };

js 精度运算

var floatObj = function() {

    // 判断obj是否为一个整数
    function isInteger(obj) {
        return Math.floor(obj) === obj
    }

    /*
     * 将一个浮点数转成整数,返回整数和倍数。如 3.14 >> 314,倍数是 100
     * @param floatNum {number} 小数
     * @return {object}
     *   {times:100, num: 314}
     */
    function toInteger(floatNum) {
        var ret = {times: 1, num: 0}
        var isNegative = floatNum < 0
        if (isInteger(floatNum)) {
            ret.num = floatNum
            return ret
        }
        var strfi  = floatNum + ''
        var dotPos = strfi.indexOf('.')
        var len    = strfi.substr(dotPos+1).length
        var times  = Math.pow(10, len)
        var intNum = parseInt(Math.abs(floatNum) * times + 0.5, 10)
        ret.times  = times
        if (isNegative) {
            intNum = -intNum
        }
        ret.num = intNum
        return ret
    }

    /*
     * 核心方法,实现加减乘除运算,确保不丢失精度
     * 思路:把小数放大为整数(乘),进行算术运算,再缩小为小数(除)
     *
     * @param a {number} 运算数1
     * @param b {number} 运算数2
     * @param digits {number} 精度,保留的小数点数,比如 2, 即保留为两位小数
     * @param op {string} 运算类型,有加减乘除(add/subtract/multiply/divide)
     *
     */
    function operation(a, b, digits, op) {
        var o1 = toInteger(a)
        var o2 = toInteger(b)
        var n1 = o1.num
        var n2 = o2.num
        var t1 = o1.times
        var t2 = o2.times
        var max = t1 > t2 ? t1 : t2
        var result = null
        switch (op) {
            case 'add':
                if (t1 === t2) {
                    // 两个小数位数相同
                    result = n1 + n2
                } else if (t1 > t2) {
                    // o1 小数位 大于 o2
                    result = n1 + n2 * (t1 / t2)
                } else {
                    // o1 小数位 小于 o2
                    result = n1 * (t2 / t1) + n2
                }
                return  (result / max).toFixed(digits);
            case 'subtract':
                if (t1 === t2) {
                    result = n1 - n2
                } else if (t1 > t2) {
                    result = n1 - n2 * (t1 / t2)
                } else {
                    result = n1 * (t2 / t1) - n2
                }
                return (result / max).toFixed(digits);
            case 'multiply':
                result = (n1 * n2) / (t1 * t2)
                return result.toFixed(digits);
            case 'divide':
                result = (n1 / n2) * (t2 / t1)
                return result.toFixed(digits);
        }
    }

    // 加
    function add(a, b, digits) {
        let value = operation(a, b, digits, "add");
        return value == NaN || value == Infinity ? 0 : value;
    }
    // 减
    function subtract(a, b, digits) {
        let value = operation(a, b, digits, "subtract");
        return value == NaN || value == Infinity ? 0 : value;
    }
    // 乘
    function multiply(a, b, digits) {
        let value = operation(a, b, digits, "multiply");
        return value == NaN || value == Infinity ? 0 : value;
    }
    // 除
    function divide(a, b, digits) {
        let value = operation(a, b, digits, "divide");
        return value == NaN || value == Infinity ? 0 : value;
    }

    return { add, subtract, multiply, divide };
}();

js 滚轮绑定

EventTarget.prototype.onMousewheel = function (fn, capture) {
    if (document.mozFullScreen !== undefined) {
        type = "DOMMouseScroll";
    } else {
        type = "mousewheel";
    }
    this.addEventListener(type, function (event) {
        event.delta = (event.wheelDelta) ? event.wheelDelta / 120 : -(event.detail || 0) / 3;
        fn.call(this, event);
    }, capture || false);
}

js 点击下载

function browserDownload (url) {
  var save_link = document.createElementNS("http://www.w3.org/1999/xhtml", "a");
  save_link.href = url;
  save_link.download = name;
  var ev = document.createEvent("MouseEvents");
  ev.initMouseEvent(
    "click",
    true,
    false,
    window,
    0,
    0,
    0,
    0,
    0,
    false,
    false,
    false,
    false,
    0,
    null
  );
  save_link.dispatchEvent(ev);
}

获取区间随机数

function random(n, m){
    var random = Math.floor(Math.random()*(m-n+1)+n);
    return random;
}

获取梯度随机数

function step_random(min, max, step) {
    var newMax = max / step;
    var randomNum = Math.floor(Math.random() * (newMax - min + 1) + min)
    var stepNum = randomNum * step
    return stepNum;
}

数据分组

function groupBy(array, valueKey) {
  let groups = {};
  let newArray = [];
  array.forEach(function(o) {
    groups[valueKey] = groups[group] || [];
    groups[valueKey].push(o);
  });
  for(const key in groups) {
     newArray = newArray.concat(groups[key]);
  }
  return newArray;
};

获取查询参数

// 方法1
function getQueryObject() {
  const search = window.location.href.split('?')[1]
  if (!search) {
    return {}
  }
  return JSON.parse(
    '{"' +
      decodeURIComponent(search)
        .replace(/"/g, '\\"')
        .replace(/&/g, '","')
        .replace(/=/g, '":"')
        .replace(/\+/g, ' ') +
      '"}'
  )
}

// 方法2
function getQueryObject(url) {
  url = url == null ? window.location.href : url;
  const search = url.substring(url.lastIndexOf("?") + 1);
  const obj = {};
  const reg = /([^?&=]+)=([^?&=]*)/g;
  search.replace(reg, (rs, $1, $2) => {
    const name = decodeURIComponent($1);
    let val = decodeURIComponent($2);
    val = String(val);
    obj[name] = val;
    return rs;
  });
  return obj;
}
posted @ 2018-10-23 08:51  戡玉  阅读(241)  评论(0编辑  收藏  举报