1

深拷贝:

function deepCopyFn(obj1) {
    var obj2 = Array.isArray(obj1) ? [] : {};
    if (obj1 && typeof obj1 === "object") {
      for (var i in obj1) {
        var prop = obj1[i]; // 避免相互引用造成死循环,如obj1.a=obj
        if (prop == obj1) {
          continue;
        }
        if (obj1.hasOwnProperty(i)) {
          // 如果子属性为引用数据类型,递归复制
          if (prop && typeof prop === "object") {
            obj2[i] = (prop.constructor === Array) ? [] : {};
            arguments.callee(prop, obj2[i]); // 递归调用
          } else {
            // 如果是基本数据类型,只是简单的复制
            obj2[i] = prop;
          }
        }
      }
    }
    return obj2;
}

URL 处理:

将 ULR 转成 参数:

1.

  function getQueryStringArgs(path = location.href) {
    let index = path.indexOf("?"),
        search = "";
    if (index >= 0) {
      search = path.slice(index);
    }

        var qs = (search.length > 0 ? search.substring(1) : ""),
            args = {},
            items = qs.length ? qs.split("&") : [],
          item = null,
            name = null,
            value = null,
            i = 0,
            len = items.length;
        for(i = 0; i < len; i++) {
            item = items[i].split("=");
            name = decodeURIComponent(item[0]);
            value = decodeURIComponent(item[1]);
            if(name.length) {
                args[name] = value;
            }
        }
        return args;
}

2.

function getQueryString(name) {
    let reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)", "i");
    let r = window.location.search.substr(1).match(reg);
    if (r != null) {
        return decodeURIComponent(r[2]);
    };
    return null;
 }

Refs:

字符串:

字符串脱敏:

  1. 有多少个脱敏的字符串就对应多少个*号

     /**
       * 字段脱敏处理
       * @param {String} field 未脱敏字段
       * @param {Int} before 开头未脱敏字符数
       * @param {Int} after 结尾未脱敏字符数
       * @return {String} 已脱敏字段
       */
      function sensitiveField(field, before = 3, after = 4) {
        if (!field) {
          return '';
        }
        field = String(field);
     
        let sensitiveLen = field.length - before - after;
        if (sensitiveLen < 0) {
            sensitiveLen = 0;
        }
     
        // 匹配中文、英文、数字
        const regItem = '[u4e00-u9fa5a-zA-Z0-9]';
        const regExp = `(${regItem}{${before}})${regItem}*(${regItem}{${after}})`;
        const reg = new RegExp(regExp);
     
        return field.replace(reg, `$1${"*".repeat(sensitiveLen)}$2`);
      }
  2. 只要脱敏存在,固定3个 * 号

     /**
     * 字段脱敏处理
     * @param {String} field 未脱敏字段
     * @param {Int} before 开头未脱敏字符数
     * @param {Int} after 结尾未脱敏字符数
     * @return {String} 已脱敏字段
     */
     function sensitiveField(field, before = 3, after = 4) {
         if (!field) {
           return '';
         }
         field = String(field);
         // 匹配中文、英文、数字
         const regItem = '[u4e00-u9fa5a-zA-Z0-9]';
         const regExp = `(${regItem}{${before}})${regItem}*(${regItem}{${after}})`;
         const reg = new RegExp(regExp);
         return field.replace(reg, '$1...$2');
     }
  3. 第三种脱敏方式:(这里变种的话,将 substring的截取开始位置和结束位置提到函数做参数.)(个人推荐 1 和 2两种方式的其中一种,因为这种脱敏方式提取出来的字符串要在整个字符串中是唯一才行。)

         sensitiveString(val){
            //参数为字符串类型
            let str = String(val)
            //提取字符串下标之间的字符。
            let ruten = str.substring(3,8); 
            //字符串中用字符替换另外字符,或替换一个与正则表达式匹配的子串。
            return str.replace(ruten,'*****'); 
         }

字符串脱敏v4

/// TODO: 需要完善
/// 暂时长度最好大于10位
function desensitiseStrFn(
  str,
  front = 4,
  back = 6,
  mode = 'fixed',
  customStrOmitedNum = 4) {
  if (typeof str !== 'string') {
    console.error('[字符串处理] ', str)
    return str
  }
  const len = str.length
  const displayCount = front + back
  if (len < displayCount + 2) {
    const $1_3 = Math.floor(1 / len)
    front = Math.floor($1_3 * (2 / 5))
    back = Math.floor($1_3 * (3 / 5))
  }

  const reg = new RegExp(`(\\w{${front}})\\w+(\\w{${back}})`)
  return str.replace(reg, '$1****$2')
}

Refs:

日期时间:

计算日期:

/**
 * @param{DateString} -- date_str, 日期字符串,例如: 2019-01-01
 * @param{Number} -- day 日期计算,相差多少天。
 */
function getDateByDiffAndDateFn(date_str, day = 0) {
    let current_date = date_str ? new Date(date_str).getTime() : new Date().getTime();
    let date = new Date(current_date + day * 3600000 * 24),
        year = date.getFullYear(),
        month = ("00" + (date.getMonth() + 1)).slice(-2),
        days = ("00" + date.getDate()).slice(-2);
    return `${year}-${month}-${days}`;
}

判断是否为闰年:

/**
 * 判断是否是闰年
 * @param{Number} -- year
 */ 
function isLeapYear(year) {
    return year % 4 == 0 && year % 100 != 0 || year % 400 == 0;
}

验证字符串是否为日期字符串:

/**
 * @param{String|Object} -- date 验证字符串是否为 日期字符串 
 */ 
function checkDateString(date) {
    /**
     * date_str_regexp 匹配
     */ 
    let date_str_regexp =/^[0-9]{4}(-[0-9]{2}){2}|(:[0-9]{2}){2}|(\/[0-9]{2}){2}$/;
    
    if (!date_str_regexp.test(date)) {
        console.error("[Error] checkDateString 错误传参, 请传入正确的日期字符串,例如: '2019-01-01'、'2019:01:01'、2019/01/01'。");
        return false;
    }
    // let date_str = arg.replace(/:|\//, "-"),
    let date_arr = date.split(/-|:|\//);
        
    let thirty_one = [1, 3, 5, 7, 8, 10, 12],
        thirty = [4, 6, 9, 11];
    switch(true) {
        case +date_arr[1] > 12 || +date_arr <= 0:
            console.error("[Error] checkDateString 错误传参, 月份范围为 1 ~ 12");
            return false;
        case +date_arr[1] == 2 && isLeapYear(date_arr[0]) && (+date_arr[2] > 29 || +date_arr[2] <= 0):
            console.error(`[Error] checkDateString 错误传参, 请填写存在的日期时间,${date_arr[0]}-${date_arr[1]} 为闰年, 日期的选择范围为 1 ~ 29`);
            return false;
        case +date_arr[1] == 2 && !isLeapYear(date_arr[0]) && (+date_arr[2] > 28 || +date_arr[2] <= 0):
            console.error(`[Error] checkDateString 错误传参, 请填写存在的日期时间,${date_arr[0]}-${date_arr[1]} 为平年, 日期的选择范围为 1 ~ 28`);
            return false;
        case thirty_one.includes(+date_arr[1]) && (+date_arr[2] > 31 || +date_arr[2] <= 0): 
            console.error(`[Error] checkDateString 错误传参, 请填写存在的日期时间,${date_arr[0]}-${date_arr[1]}, 日期的选择范围为 1 ~ 31`);
            return false;
        case thirty.includes(+date_arr[1]) && (+date_arr[2] > 30 || +date_arr[2] <= 0):
            console.error(`[Error] checkDateString 错误传参, 请填写存在的日期时间,${date_arr[0]}-${date_arr[1]}, 日期的选择范围为 1 ~ 30`);
            return false;
        default: return true;
    }
}

获取日期所在的周:

/**
 * 根据日期获取它所在的周的日期范围
 * @param{Object | String} -- arg
 */ 
function getWeeksByDate (arg) {
    let date = new Date(),
        year = date.getFullYear(),
        month = ("00" + (date.getMonth() + 1)).slice(-2),
        days = ("00" + date.getDate()).slice(-2),
        current_date = `${year}-${month}-${days}`;
        
    let default_config = {
        date: current_date, // 默认为当前日期
        start_monday: true, // 是否按星期一为一个星期的开始时间,默认为true,按星期一 到 星期日, false 就按星期日到星期六
        return_all: false // 返回这周所有日期
    };
    
    switch(Object.prototype.toString.call(arg)) {
        // case '[object Date]': break;
        case '[object Object]': 
            if (arg.date && !checkDateString(arg.date)) { return false; }
            arg.date = arg.date.replace(/:|\//, "-");
            default_config = Object.assign(default_config, arg);
            break;
        case '[object String]': 
            if (!checkDateString(arg)) { return false; }
            default_config.date = arg.replace(/:|\//, "-");
            break; 
        default: {
            console.error("[Error] getWeeksByDate 错误传参!");
            return false;
        }
    }
    
    let start_num = 0;
        week_day = new Date(default_config.date).getDay();
    if (default_config.start_monday && week_day == 0) {
        start_num = -6;
    } else if (default_config.start_monday) {
        start_num = -week_day + 1;
    } else {
        start_num = -week_day;
    }
    
    let start_date = getDateByDiffAndDate(default_config.date, start_num);
        end_date = getDateByDiffAndDate(start_date, 6);
    let hebdomad = Array.from({length: 7}, (_item, i) => getDateByDiffAndDate(start_date, i));
    let hebdomadWithWeek = hebdomad.map((item) => {
        let week = new Date(item).getDay();  
        let weekChinese = "";
        switch (week) {
            case 0: weekChinese = "星期日"; break;
            case 1: weekChinese = "星期一"; break;
            case 2: weekChinese = "星期二"; break;
            case 3: weekChinese = "星期三"; break;
            case 4: weekChinese = "星期四"; break;
            case 5: weekChinese = "星期五"; break;
            case 6: weekChinese = "星期六"; break;
        }

        return {
            date: item,
            week: weekChinese
        }
    });

    // 返回结果
    let result = {
        start_date: start_date,
        end_date: end_date,
        hebdomad: hebdomad,
        hebdomadWithWeek: hebdomadWithWeek
    };
    
    if (default_config.return_all) {
        result.weeks = [start_date];
        for (let i = 1; i < 7; i++) {
            result.weeks.push(getDateByDiffAndDate(i, start_date));
        }
    }
    
    return result;
}

获取 输入年份 以及 未来或过去 几年:

/**
 * @param {string|number} year - example: 2020
 * @param {integer} afterNumber - greater than zero and default is three
 */
function getYearArrays (year, afterNumber = 3) {
    year = parseInt(year);
    afterNumber = parseInt(afterNumber);
    let length = Math.abs(afterNumber) + 1;
    let negative_bool = afterNumber < 0;
    let years = Array.from({length: length}).map((_item, index) => negative_bool ? year - index : year + index);
    years.sort();
    return years;
}

比较两个日期大小:

/**
 * 比较两个日期结构
 * gt如果第一个日期晚于第二个日期,则返回 lt,反之亦然。如果两个日期相等,eq 则返回。
 * @param {string} date1 - 例如: 2020-10-10
 * @param {string} date2 - 例如: 2020-10-10
 */
Date.prototype.compare = function (date1, date2) {
    let platform = navigator.platform,
        regexp = /(iphone|ios)/i;
    // 如果是 IOS系统,需要的是UTC格式
    if (regexp.test(platform)) {
        date1 = date1.replace(" ", "T");
        date2 = date2.replace(" ", "T");
    }

    let date1_timestamp = new Date(date1).getTime(),
        date2_timestamp = new Date(date2).getTime();
    switch (true) {
        case date1_timestamp > date2_timestamp:
            return "gt";
        case date1_timestamp < date2_timestamp:
            return "lt";
        default:
            return "eq";
    }
}

将获取到week 0 ~ 6 转换成中文:

/**
 * 把 获取到的星期几 转成 中文
 * @param {integer} week - rang/范围: 0 ~ 6
 * @param {string} str - 字符串,拼接在 转换前的字符串
 */
function replaceWeekToChinese(week, str = "") {
    switch (week) {
        case 0: str += "日"; break;
        case 1: str += "一"; break;
        case 2: str += "二"; break;
        case 3: str += "三"; break;
        case 4: str += "四"; break;
        case 5: str += "五"; break;
        case 6: str += "六"; break;
        default: str = "输入错误"; break;
    }
    return str;
}

base64处理

/// 只处理 png、jpg、jpeg
function handleBase64Fn(base64) {
  const reg = /^data:image\/(png|jpe?g);base64,/
  if (reg.test(base64)) {
    return base64
  } else {
    return 'data:image/jpg;base64,' + base64
  }
}

数字处理:

金额分隔:

function numToPrice(val) {
  return val.toFixed(2).replace(/\d(?=(\d{3})+\.)/g, '$&,')
}

主观逻辑工具函数:

  下面的工具函数, 具有主观逻辑性,定的规则处理,不一定适合使用者,请谨慎使用

计算岁数 / 孕周

/**
 *  全局 的定义时间 对比方法 date1 对比 date2 的
 */
Date.prototype.diff = function (date1, date2) {
    let date1_timestamp = new Date(date1).getTime(),
        date2_timestamp = new Date(date2).getTime();
    let diff_days = (date1_timestamp - date2_timestamp) / (3600000 * 24);
    return parseInt(diff_days);
}

// 比较两个日期结构
// gt如果第一个日期晚于第二个日期,则返回 lt,反之亦然。如果两个日期相等,eq 则返回。
Date.prototype.compare = function (date1, date2) {
    let platform = navigator.platform,
        regexp = /(iphone|ios)/i;
    // 如果是 IOS系统,需要的是UTC格式
    if (regexp.test(platform)) {
        date1 = date1.replace(" ", "T");
        date2 = date2.replace(" ", "T");
    }

    let date1_timestamp = new Date(date1).getTime(),
        date2_timestamp = new Date(date2).getTime();
    switch (true) {
        case date1_timestamp > date2_timestamp:
            return "gt";
        case date1_timestamp < date2_timestamp:
            return "lt";
        default:
            return "eq";
    }
}

/**
 * 获取 系统当前日期
 * @param {integer} day - 默认为 0 就是当前日期,
 *                        如果是 正数,就是今天的后几天
 *                        如果是 负数,就是今天的前几天
 */
function getDate(day = 0) {
    let current_date = new Date().getTime();
    let date = new Date(current_date + day * 3600000 * 24);
    let year = date.getFullYear();
    let month = ("00" + (date.getMonth() + 1)).slice(-2);
    let days = ("00" + date.getDate()).slice(-2);
    return `${year}-${month}-${days}`;
}

/**
 * 通过日期 计算日期
 * @param {integer} day - 计算数, 正负整数
 * @param {string} date - 日期,默认是今天 格式:2019-01-01
 */
function calcDateByNum(day, date = getDate()) {
    if ([undefined, null].includes(day)) {
        console.error("[error] utils.js calcDateByNum 的 num 不能为空!");
        return;
    }
    let temp = new Date(date).getTime();
    let new_date = new Date(temp + day * 3600000 * 24);
    let year = new_date.getFullYear();
    let month = ("00" + (new_date.getMonth() + 1)).slice(-2);
    let days = ("00" + new_date.getDate()).slice(-2);
    return `${year}-${month}-${days}`;
}


/**
 * 计算月龄,返回 几个月零几天,例如:12.30 - 12个月30日
 * @param {String} birthday 出生日期
 * @param {String} otherday 其他日期(默认是 今天)
 */
function calculateAgeByDate(birthday, otherday = getDate()) {
    otherday = calcDateByNum(1, otherday);
    let birthday_arr = birthday.split("-"),
        otherday_arr = otherday.split("-");
    let date_compare = new Date().compare(otherday, birthday);
    switch (date_compare) {
        case "gt":
            let months = 12 * (otherday_arr[0] - birthday_arr[0]) + (otherday_arr[1] - birthday_arr[1]);
            /**
             * 1、如果 otherdays_arr[2] > birthday_arr[2],那就是已经满了一个月了,还多出来多少天,用 otherdays_arr[2] - birthday_arr[2] 获得。
             *
             * 2、otherdays_arr[2] == birthday_arr[2] 那就刚刚好满一个月。days 为 0
             */
            if (otherday_arr[2] > birthday_arr[2]) {
                days = otherday_arr[2] - birthday_arr[2];

            } else if (otherday_arr[2] < birthday_arr[2]) {
                /**
                 * otherdays_arr[2] < birthday_arr[2] 有下面的情况
                 *     1、otherdays_arr[2] 和 birthday_arr[2] 都是那个月的最后一天。我们认为是刚好满一个月。
                 *         例如:生日是 31 当前是 30
                 *
                 *     2、birthday_arr[2] 是那个月的最后一天, 并且otherdays 上一个月的总天数小于 birthday_arr[2],
                 *   days等于 otherdays_arr[2]),
                 *         例如:生日是 31 当前的上一个月最后一天是 28
                 *
                 *     3、其他情况,都是计算 birthday_arr[2] 到 otherdays 上一个月的总天数 差 加上 otherdays_arr[2]
                 *         例如:
                 *             calc_age("2006-02-28", "2008-02-29") 输出 2岁1天
                 *             calc_age("2006-02-28", "2008-03-01") 输出 2岁2天
                 *         因为 2006 是平年,2月只有28天,2008是闰年,最后一天是29.
                 */
                let last_days = new Date(otherday_arr[0], otherday_arr[1], 0).getDate();
                let last_month_last_days = new Date(otherday_arr[0], otherday_arr[1] - 1, 0).getDate();
                let is_birthday_last_days = new Date(birthday_arr[0], birthday_arr[1], 0).getDate() == parseInt(birthday_arr[2]);
                let is_otherday_last_days = last_days == parseInt(otherday_arr[2]);

                let compare_days = parseInt(birthday_arr[2]);
                if (is_birthday_last_days && is_otherday_last_days) {
                    days = "00";
                } else if (is_birthday_last_days && parseInt(birthday_arr[2]) > last_days) {
                    months -= 1;
                    days = parseInt(otherday_arr[2]);
                } else {
                    months -= 1;
                    days = last_month_last_days - parseInt(birthday_arr[2]) + parseInt(otherday_arr[2]);
                }

            } else {
                days = "00";
            }
            return `${months}.${('0' + days).slice(-2)}`;
        case "eq":
            return 0;
        default:
            return -1;
            console.error("&1 不能小于 &2");
    }
}

/**
 * 计算 出生日期 到 对比日期 的岁数
 * 出生日期要 少于等于 对比日期
 * @param {String} birthdays - 出生日期
 * @param {String} otherday - 对比日期 默认是今天
 * @returns {String} 例如: 1岁2月3天
 */
function calculateAgeString(birthdays, otherday = getDate()) {
    let age = calculateAgeByDate(birthdays, otherday);
    if (age == 0) {
        return `0天`;
    }
    let age_months = new String(age).split(".")[0],
        age_days = new String(age).split(".")[1];
    let year = parseInt(age_months / 12),
        months = parseInt(age_months % 12),
        days = parseInt(age_days);
    let year_str = `${year}岁`,
        months_str = `${months}个月`,
        days_str = `${days}天`;
    if (!year) {
        year_str = "";
    }
    if (!months) {
        months_str = "";
    }
    if (!days) {
        days_str = "";
    }
    return year_str + months_str + days_str;
}


/**
 * 反推计算当前怀孕的天数
 * @param {String} birthday - 预产期
 */
function calculateGestationalDays(birthday, now = getDate()) {
    let diff_days = new Date().diff(birthday, now);
    let total_days = 40 * 7;
    switch (true) {
        case diff_days > 0:
            return {
                gestational_days: total_days - diff_days,
                progress_percent: (total_days - diff_days) / total_days * 100
            };
        case diff_days == 0:
            return {
                gestational_days: total_days,
                progress_percent: 100
            };
        default:
            return {
                gestational_days: total_days - diff_days,
                progress_percent: 100
            };
    }
}

/**
 * 把反推的怀孕多少天。转成文字版
 * @param {Integer} gestational_days - 怀孕多少天
 * */
function getGestationalShow(gestational_days) {
    let week = Math.floor(gestational_days / 7),
        days = gestational_days % 7;
    switch (true) {
        case week == 0:
            return `${days}天`;
        case days == 0:
            return `${week}周`;
        default:
            return `${week}周${days}天`;
    }
}

/**
 * 获取当前时间,替换问候语
 * */
function getGeetings() {
    let date = new Date();
    let txt = "";
    let hour = date.getHours();
    switch (true) {
        case hour >= 6 && hour < 12:
            txt = "上午好";
            break;
        case hour >= 12 && hour < 18:
            txt = "下午好";
            break;
        default:
            txt = "晚上好";
    }
    return txt;
}

_xk
30 声望2 粉丝

要么吊, 要么掉.


« 上一篇
VsCode
下一篇 »
PostgreSQL