[更新中]一些常用的JS手写功能

1、对象深拷贝

function deepClone(obj) {
  const _toString = Object.prototype.toString

  // null, undefined, non-object, function
  if (!obj || typeof obj !== 'object') {
    return obj
  }

  // DOM Node
  if (obj.nodeType && 'cloneNode' in obj) {
    return obj.cloneNode(true)
  }

  // Date
  if (_toString.call(obj) === '[object Date]') {
    return new Date(obj.getTime())
  }

  // RegExp
  if (_toString.call(obj) === '[object RegExp]') {
    const flags = []
    if (obj.global) { flags.push('g') }
    if (obj.multiline) { flags.push('m') }
    if (obj.ignoreCase) { flags.push('i') }

    return new RegExp(obj.source, flags.join(''))
  }

  const result = Array.isArray(obj) ? [] : obj.constructor ? new obj.constructor() : {}

  for (const key in obj) {
    result[key] = deepClone(obj[key])
  }
  return result
}

2、wind-dom 插件源码中的 hasClassaddClassremoveClass

多看看人家写的源码,精简优美,涨姿势。

var trim = function (string) {
  return (string || '').replace(/^[\s\uFEFF]+|[\s\uFEFF]+$/g, '');
};

var hasClass = function (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;
  }
};

var addClass = function (el, cls) {
  if (!el) return;
  var curClass = el.className;
  var classes = (cls || '').split(' ');

  for (var i = 0, j = classes.length; i < j; i++) {
    var 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;
  }
};

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

  for (var i = 0, j = classes.length; i < j; i++) {
    var 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);
  }
};

3、判断一个变量是否为空数组

var arr = [];
// Array.isArray是ES5提供的,如果不支持。用下面的方案重写Array.isArray()方法,这种操作是叫重写吧?
if (!Array.isArray) {
  Array.isArray = function(arg) {
    return Object.prototype.toString.call(arg) === '[object Array]';
  };
}
if(Array.isArray(arr) && arr.length === 0){
    console.log('是空数组');
}

4、实现一个函数clone,可以对JavaScript中的5种主要的数据类型(包括Number、String、Object、Array、Boolean)进行值复制。

 /**
 * 对象克隆
 * 支持基本数据类型及对象
 * 递归方法
 */
function clone(obj) {
    var o;
    switch (typeof obj) {
        case "undefined":
            break;
        case "string":
            o = obj + "";
            break;
        case "number":
            o = obj - 0;
            break;
        case "boolean":
            o = obj;
            break;
        case "object": // object 分为两种情况 对象(Object)或数组(Array)
            if (obj === null) {
                o = null;
            } else {
                if (Object.prototype.toString.call(obj).slice(8, -1) === "Array") {
                    o = [];
                    for (var i = 0; i  obj.length; i++) {
                        o.push(clone(obj[i]));
                    }
                } else {
                    o = {};
                    for (var k in obj) {
                        o[k] = clone(obj[k]);
                    }
                }
            }
            break;
        default:
            o = obj;
            break;
    }
    return o;
}

5、统计字符串”aaaabbbccccddfgh”中字母个数或统计最多字母数。

var str = "aaaabbbccccddfgh";
var obj  = {};
for(var i=0;istr.length;i++){
    var v = str.charAt(i);
    if(obj[v] & obj[v].value == v){
        obj[v].count = ++ obj[v].count;
    }else{
        obj[v] = {};
        obj[v].count = 1;
        obj[v].value = v;
    }
}
for(key in obj){
    document.write(obj[key].value +'='+obj[key].count+' '); 
    // a=4  b=3  c=4  d=2  f=1  g=1  h=1 
}

6、写一个function,清除字符串前后的空格。(兼容所有浏览器)

function trim(str) {
    if (str & typeof str === "string") {
        return str.replace(/(^s*)|(s*)$/g,""); //去除前后空白符
    }
}

7、二维数组转成一维数组

let data = [
        {
          id: '1',
          label: '1',
          sort: 1,
          children:[
          { pid: null, label: '1-1', sort: null },
          { pid: null, label: '1-2', sort: null },]
        },{
          id: '2',
          label: '2',
          sort: 2,
          children:[
          { pid: null, label: '2-1', sort: null },
          { pid: null, label: '2-2', sort: null },]
        }]        
let b = data.flatMap(i=>{
    i.children.map((j,index)=>{
        j.pid = i.id;
        j.sort = index
    });
    let a = i.children;
    delete i.children;
    a.unshift(i);
    console.log(a);
    return a
});
console.log(b);

8、获取url参数

//1
function getParams(url) {
    const res = {}
    if (url.includes('?')) {
        const str = url.split('?')[1]
        const arr = str.split('&')
        arr.forEach(item => {
            const key = item.split('=')[0]
            const val = item.split('=')[1]
            res[key] = decodeURIComponent(val) // 解码
        })
    }
    return res
}

// 测试
const user = getParams('http://www.baidu.com?user=%E9%98%BF%E9%A3%9E&age=16')
console.log(user) // { user: '阿飞', age: '16' }

//2
// 创建一个URLSearchParams实例
const urlSearchParams = new URLSearchParams(window.location.search);
// 把键值对列表转换为一个对象
const params = Object.fromEntries(urlSearchParams.entries());

9、判断设备类型

// 判断手机 or 电脑
if ((navigator.userAgent.match(/(iPhone|iPod|Android|ios|iOS|iPad|Backerry|WebOS|Symbian|Windows Phone|Phone)/i))) {
    console.log("手机访问.")
} else {
    console.log("电脑访问.")
}

10、判断浏览器类型

var Sys = {};
var ua = navigator.userAgent.toLowerCase();
var s;
(s = ua.match(/msie ([\d.]+)/))
    ? (Sys.ie = s[1])
    : (s = ua.match(/firefox\/([\d.]+)/))
        ? (Sys.firefox = s[1])
        : (s = ua.match(/chrome\/([\d.]+)/))
            ? (Sys.chrome = s[1])
            : (s = ua.match(/opera.([\d.]+)/))
                ? (Sys.opera = s[1])
                : (s = ua.match(/version\/([\d.]+).*safari/))
                    ? (Sys.safari = s[1])
                    : 0;
if (Sys.ie) console.log('IE: ' + Sys.ie);
if (Sys.firefox) console.log('Firefox: ' + Sys.firefox);
if (Sys.chrome) console.log('Chrome: ' + Sys.chrome);
if (Sys.opera) console.log('Opera: ' + Sys.opera);
if (Sys.safari) console.log('Safari: ' + Sys.safari);

11、保留两位小数

// js保留两位小数方法总结
var num = 2.446242342;
num = num.toFixed(2); // 输出结果为 2.45

Math.floor(15.7784514000 * 100) / 100 // 输出结果为 15.77

Number(15.7784514000.toString().match(/^\d+(?:\.\d{0,2})?/)) // 输出结果为 15.77,不能用于整数如 10 必须写为10.0000

//四舍五入保留2位小数(若第二位小数为0,则保留一位小数)
function keepTwoDecimal(num) {
    var result = parseFloat(num);
    if (isNaN(result)) {
        alert('传递参数错误,请检查!');
        return false;
    }
    result = Math.round(num * 100) / 100;
    return result;
}
//四舍五入保留2位小数(不够位数,则用0替补)
function keepTwoDecimalFull(num) {
    var result = parseFloat(num);
    if (isNaN(result)) {
        alert('传递参数错误,请检查!');
        return false;
    }
    result = Math.round(num * 100) / 100;
    var s_x = result.toString();
    var pos_decimal = s_x.indexOf('.');
    if (pos_decimal < 0) {
        pos_decimal = s_x.length;
        s_x += '.';
    }
    while (s_x.length <= pos_decimal + 2) {
        s_x += '0';
    }
    return s_x;
}

//保留两位小数
//功能:将浮点数四舍五入,取小数点后2位 
function toDecimal(x) {
    var f = parseFloat(x);
    if (isNaN(f)) {
        return;
    }
    f = Math.round(x * 100) / 100;
    return f;
}

//制保留2位小数,如:2,会在2后面补上00.即2.00 
function toDecimal2(x) {
    var f = parseFloat(x);
    if (isNaN(f)) {
        return false;
    }
    var f = Math.round(x * 100) / 100;
    var s = f.toString();
    var rs = s.indexOf('.');
    if (rs < 0) {
        rs = s.length;
        s += '.';
    }
    while (s.length <= rs + 2) {
        s += '0';
    }
    return s;
}

function fomatFloat(src, pos) {
    return Math.round(src * Math.pow(10, pos)) / Math.pow(10, pos);
}
//四舍五入 
alert("保留2位小数:" + toDecimal(3.14159267));
alert("强制保留2位小数:" + toDecimal2(3.14159267));
alert("保留2位小数:" + toDecimal(3.14559267));
alert("强制保留2位小数:" + toDecimal2(3.15159267));
alert("保留2位小数:" + fomatFloat(3.14559267, 2));
alert("保留1位小数:" + fomatFloat(3.15159267, 1));

//五舍六入 
alert("保留2位小数:" + 1000.003.toFixed(2));
alert("保留1位小数:" + 1000.08.toFixed(1));
alert("保留1位小数:" + 1000.04.toFixed(1));
alert("保留1位小数:" + 1000.05.toFixed(1));

//科学计数 
alert(3.1415.toExponential(2));
alert(3.1455.toExponential(2));
alert(3.1445.toExponential(2));
alert(3.1465.toExponential(2));
alert(3.1665.toExponential(1));
//精确到n位,不含n位 
alert("精确到小数点第2位" + 3.1415.toPrecision(2));
alert("精确到小数点第3位" + 3.1465.toPrecision(3));
alert("精确到小数点第2位" + 3.1415.toPrecision(2));
alert("精确到小数点第2位" + 3.1455.toPrecision(2));
alert("精确到小数点第5位" + 3.141592679287.toPrecision(5));

12、js封装获取DOM对象的方法

//取对象的封装
function $(eleStr) {
    //为了区分,不同的取对象方式,以加前缀的方式来区分
    //id加#  class加.  name加_  tagName不加前缀
    switch (eleStr.substr(0, 1)) {
        case '#':
            return document.getElementById(eleStr.substr(1))
            break
        case '.':
            return document.getElementsByClassName(eleStr.substr(1))
            break
        case '_':
            return document.getElementsByName(eleStr.substr(1))// 查询元素的 name 属性
            break
        default:
            return document.getElementsByTagName(eleStr)
            break
    }
}

13、防抖

// 防抖
function debounce(fn, delay) {
    // 定时器
    let timer = null
    // 将debounce处理结果当作函数返回
    return function () {
        // 保留调用时的this上下文
        let context = this
        // 保留调用时传入的参数
        let args = arguments
        // 每次事件被触发时,都去清除之前的旧定时器
        if (timer) {
            clearTimeout(timer)
        }
        // 设立新定时器
        timer = setTimeout(function () {
            fn.apply(context, args)
        }, delay)
    }
}
function fun() {
	console.log('fun')
}
const debounceTask = debounce(fun, 1000)
window.addEventListener('scroll', debounceTask)

14、节流

function throttle(fn, delay) {
  let last = 0 // 上次触发时间
  return (...args) => {
    const now = Date.now()
    if (now - last > delay) {
      last = now
      fn.apply(this, args)
    }
  }
}

// 测试
function task() {
  console.log('run task')
}
const throttleTask = throttle(task, 1000)
window.addEventListener('scroll', throttleTask)

15、倒计时

// 倒计时
var now = (new Date()).valueOf();
var startTime = now.toString().substr(0, 10) //开始时间
var endTime = 1643904000; //结束时间
var lasttimer = setInterval(function () {
    var ts = endTime - startTime; //计算剩余的毫秒数
    if (ts > 0) {
        var dd = parseInt(ts / 60 / 60 / 24, 10); //计算剩余的天数
        var hh = parseInt(ts / 60 / 60 % 24, 10); //计算剩余的小时数
        var mm = parseInt(ts / 60 % 60, 10); //计算剩余的分钟数
        var ss = parseInt(ts % 60, 10); //计算剩余的秒数
        dd = dd < 10 ? ('0' + dd) : dd
        hh = hh < 10 ? ('0' + hh) : hh
        mm = mm < 10 ? ('0' + mm) : mm
        ss = ss < 10 ? ('0' + ss) : ss
        $('.time').html('<span>' + dd + '</span>天<span>' + hh + '</span>时<span>' + mm + '</span>分<span>' + ss + '</span>秒')
        startTime++;
    } else if (ts < 0) {
        $('.time').html('<span>00</span>天<span>00</span>时<span>00</span>分<span>00</span>秒')
        clearInterval(lasttimer)
    }
}, 1000);

16、输入框实时校验

// 输入框实时校验
$(window).load(function () {
    $(".myinput").on("input propertychange", function () {
	    let str = $(this).val()
        if (isNaN(str)) {
            $(this).css('border', '2px solid red')
            setTimeout(() => {
                $(this).val('')//清空
            }, 1000)
        } else {
            $(this).css('border', '1px solid #666')
        }
    })
})
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值