阅读 14032

JS方法速查

🔥前言

首先这个文章是一个不断维护的项目,励志,如果各位朋友有更好的解决方法,欢迎在下方评论,我也会第一时间感谢和更新文章内容的,拜谢!!!


更新记录(只显示最近5条)

  • 增加 常用DOM接口 && 常见的XSS转义场景(2019.9.2)
  • 优化Array,Date 部分内容(2019.7.12)
  • 优化其他部分 - 常用正则速查表现形式(增加了示例等)(2019.7.4)快速跳转
  • 其他部分 增加了 Math函数的一些应用 和 常用正则速查 (2019.7.2)
  • 致谢:A、让你一眼就看到我。| 大湿胸。| Adaer | 你的宇哥哥 | jNane | Felix_俊锴

🌲数组

1.数组去重

let arrs = [1,2,2,3,3,6,5,5];

// ES6
[...new Set(arr)] // [1,2,3,6,5]
// 此方法也能去除数组中重复的项:[...new Set('ababbc')].join('') // abc

// 其他方法
function uniq(array){
    let temp = [];
    let l = array.length;
    for(let i = 0; i < l; i++) {
        for(let j = i + 1; j < l; j++){
            if (array[i] === array[j]){
                i++;
                j = i;
            }
        }
        temp.push(array[i]);
    }
    return temp;
}
console.log(uniq(arrs)); // [1,2,3,6,5]
复制代码

数组去重拓展(传参数 指定去除哪个重复的,未完成)


2.数组合并

let arr1 = [1,2,3]
let arr2 = [4,5,6]

// ES6
[...arr1, ...arr2] // [1, 2, 3, 4, 5, 6]


// 方法2:concat方法(挂载Array原型链上)
let c = a.concat(b);
console.log(c); // [1, 2, 3, 4, 5, 6]
console.log(a); // [1, 2, 3]  不改变本身
// 备注:看似concat似乎是 数组对象的深拷贝,其实,concat 只是对数组的第一层进行深拷贝

// 方法3:apply方法
Array.prototype.push.apply(a, b);
console.log(a); // [1, 2, 3, 4, 5, 6] 改变原目标数组
console.log(b); // [4, 5, 6]

复制代码

3.数组排序(sort)

let objArr = [
  {name: 'test1', age: 20},
  {name: 'test1', age: 22},
  {name: 'test1', age: 21}
]

// 第一参数a, 第二参数b ---> a-b升序(从小到大);b-a降序(从大到小),原理就是 两数计算,如果返回的是负数,就保留前者(我可能说的不对,欢迎纠正)
objArr.sort((a, b) => {
  return a.age - b.age
}) 
// 结果会按照年龄从小到大的顺序排列


复制代码

4.多维数组转一维数组(flat)

let arr = [1, [2], [[3], 4], 5];

// ES6 数组的flat()
arr.flat() // [1, 2, Array(1), 4, 5] 如果这样写的话只能展开二维数组,但是可以加参数Infinity,就是能展开多维数组
arr.flat(Infinity) // [1, 2, 3, 4, 5] 注意如果原数组有空位,flat()方法会跳过空位

// 其他方法
const deepFlatten = arr => [].concat(...arr.map(v => (Array.isArray(v) ? deepFlatten(v) : v)));
deepFlatten(arr); // [1,2,3,4,5]


// 执行效率验证(拓展)
// let start = new Date().getTime();
// console.log('reduceDimension: ', deepFlatten([1, [2], [[3], 4], 5]);
// console.log('耗时: ', new Date().getTime() - start); // *ms

// ES6 数组的flatMap() 方法大家可以自行查阅一下,拓展下自己的知识面
复制代码

5.过滤数组(filter)

let json = [
  { id: 1, name: 'john', age: 24 },
  { id: 2, name: 'zkp', age: 21 },
  { id: 3, name: 'mike', age: 50 }
];

// ES6
json.filter( item => item.age > 22) // [{id: 1, name: 'john', age: 24}, { id: 3, name: 'mike', age: 50 }]

// ES5

复制代码

6.判断数组中的项是否满足于某个条件(some,every)

let arr = [4, 2, 3]

// ES6 some方法(有符合)
arr.some( item => item > 1) // true
arr.some( item => item > 3) // true

// ES5 every(全符合)

arr.every(item => item > 1) // true
arr.every(item => item > 3) // false

// 注意:上面两个有不同哦,一个是有符合的判定,一个是全符合的判定
复制代码

7.操作数组中的每一项,并使其按照一定的逻辑返回(map)

var potatos = [
  { id: '1001', weight: 50 },
  { id: '1002', weight: 80 },
  { id: '1003', weight: 120 },
  { id: '1004', weight: 40 }
]

// ES6写法
const fn = (arr, key) => arr.map(arr =>  arr[key])

fn(potatos, 'id') // ["1001", "1002", "1003", "1004"]
fn(potatos, 'weight') // [50, 80, 120, 40]
复制代码

8.其他常用的ES6 Array方法

// forEach() 遍历数组

// pop() 删除数组中最后一个元素,并返回该元素的值。此方法更改数组的长度

// shift() 删除数组中第一个元素,并返回该元素的值。此方法更改数组的长度

// push() 将一个或多个元素添加到数组的末尾,并返回该数组的新长度

// unshift() 将一个或多个元素添加到数组的开头,并返回该数组的新长度(该方法修改原有数组)

// 🔥Array.prototype.filter() 创建一个新数组, 其包含通过所提供函数实现的测试的所有元素,不会改变原有值,如果没符合的返回[]
let arr = [1, 2, 3]
arr.filter( x => x > 1) // [2, 3]

// Array.prototype.join() 将一个数组(或一个类数组对象)的所有元素连接成一个字符串并返回这个字符串
['Fire', 'Air', 'Water'].join() // "Fire,Air,Water"

// Array.prototype.slice() 取出任意元素, | 参数一:从哪开始,参数二(可选)结束位置,不选的话 就节选到最后了
[1, 2, 3].slice(0, 1) // [1]

// Array.prototype.splice() 删除任意元素,操作任意元素 | 参数一:从哪开始 | 参数二:操作元素的个数 | 参数三:插入元素的值...(可以写多个参数三)
[1, 2, 3].splice(0, 1) // 删除 [2, 3]

// Array.prototype.includes() 用来判断一个数组是否包含一个指定的值,根据情况,如果包含则返回 true,否则返回false。
[1, 2, 3].includes(1) // true

// Array.prototype.reverse() 颠倒数组
[1, 2, 3].reverse() // [3, 2, 1]

复制代码

点击此处,查看更多方法详细链接


9.获得数组最大最小值


// 使用 Math 中的 max/min 方法
let arr = [22,13,6,55,30];

// ES6
Math.max(...arr); // 55
Math.min(...arr); // 6

// ES5
Math.max.apply(null, arr); // 55
Math.min.apply(null, arr); // 6

复制代码

10.获取数组交集

// ES6 写法
const similarity = (arr1, arr2) => arr1.filter(v => arr2.includes(v));
similarity([1, 2, 3], [1, 2, 4]); // [1,2]

// ES5 写法
// function similarity(arr1, arr2) {
//   return arr2.filter(function(v) {
//     return arr1.includes(v)
//   })
// }
复制代码

11.数组对象去重

let arr = [
  {id: 1, name: 'Jhon1'},
  {id: 2, name: 'sss'},
  {id: 3, name: 'Jhon2'},
  {id: 4, name: 'Jhon3'}
]

// ES6
const uniqueElementsBy = (arr, fn) =>arr.reduce((acc, v) => {if (!acc.some(x => fn(v, x))) acc.push(v);return acc;}, []);

// 下面的示例表示,去重依据是 id ,就是 id一样的,只留下一个
uniqueElementsBy(arr, (a, b) => a.id === b.id) // [{id: 1, name: 'Jhon1'}, {id: 2, name: 'sss'}]

复制代码

12.数组乱序

function shuffle(arr) {
  let array = arr
  let index = array.length

  while (index) {
    index -= 1
    let randomInedx = Math.floor(Math.random() * index)
    let middleware = array[index]
    array[index] = array[randomInedx]
    array[randomInedx] = middleware
  }

  return array
}

let arr = [1,2,3,4,5]
shuffle(arr) // [3, 4, 2, 5, 1] 结果不定
复制代码

还有更简单的方式,欢迎来撩


13.检查数组中某元素出现的次数

function countOccurrences(arr, value) {
  return arr.reduce((a, v) => v === value ? a + 1 : a + 0, 0);
}

let arr = [1,2,3,4,1,2,4]
countOccurrences(arr, 1) // 2
复制代码

14.检查数组中的所有元素是否相等

const allEqual = arr => arr.every(val => val === arr[0]);

// 示例
allEqual([1, 2, 3, 4, 5, 6]); // false
allEqual([1, 1, 1, 1]); // true
复制代码

15.数组对象,求某一列属性的总和

var potatos = [
  { id: '1001', weight: 50 },
  { id: '1002', weight: 80 },
  { id: '1003', weight: 120 },
  { id: '1004', weight: 40 }
]

// ES6写法
const fn = (arr, key) => arr.reduce((sum, p) => { return p[key] + sum },0)

fn(potatos, 'weight') // 290
fn(potatos, 'id') // "10041003100210010" 字符串相加就是这个结果,如果有各自的需求,可以自己加上
复制代码

16.分割数组,并操作每一项数组(函数)

/**
 * 数组分隔方法,并且可以传入一个处理函数,用来分隔之前处理数组的每一项
 * 
 * @category Array
 * @param {Array} array 需要处理的数组
 * @param {number} [size = 1] 每个数组区块的长度
 * @param {Function} [fn = item => item] 函数
 * @returns {Array} 返回一个包含拆分区块的新数组(相当于一个二维数组)。
 * @example
 *
 * chunk(['a', 'b', 'c', 'd'], 2)
 * // => [['a', 'b'], ['c', 'd']]
 *
 * chunk(['a', 'b', 'c', 'd'], 3)
 * // => [['a', 'b', 'c'], ['d']]
 *
 * chunk([1, 2, 3, 4], 3, item => item * 2)
 * // => [[2, 4, 6], [8]]
 */

function chunk(array, size = 1, fn = item => item) {
    
    array = array.map(fn)

    size = Math.max(size, 0) // 这一句就很妙,当传入值小于0的时候,置为0,大于0的时候,不写,但不知道性能怎么样
    const length = array == null ? 0 : array.length
    if (!length || size < 1) {
      return []
    }
    let index = 0
    let resIndex = 0
    const result = new Array(Math.ceil(length / size))
  
    while (index < length) {
      result[resIndex++] = array.slice(index, (index += size))
    }
    return result
}
复制代码

👫对象

1.对象合并


// 1️⃣ ES6方法

let obj1 = {
    a:1,
    b:{ 
        b1:2 
    }
}

let obj2 = { c:3, d:4 }

console.log({...obj1, ...obj2}) // {a: 1, b: {…}, c: 3, d: 4}
// 支持无限制合并,但如果对象之间存在相同属性,则后面属性会覆盖前面属性。*请注意,这仅适用于浅层合并。


// 2️⃣ Obj.assign():可以把任意多个的源对象自身的可枚举属性拷贝给目标对象,然后返回目标对象
let o1 = { a: 1 };
let o2 = { b: 2 };

let obj = Object.assign(o1, o2);
console.log(obj); // { a: 1, b: 2 }
console.log(o1);  // { a: 1, b: 2 }, 且 **目标对象** 自身也会改变(也就是assign第一个对象)
console.log(o2); // { b: 2 } 不改变

// 备注:Object.assign() 拷贝的是属性值。假如源对象的属性值是一个指向对象的引用,它也只拷贝那个引用值
// 备注:数组合并用 concat() 方法


// 3️⃣ $.extend()

复制代码

2.浅拷贝,深拷贝

深拷贝(基础版)


/**
 * 此函数,可以完全生成一个新的拷贝对象,也可以将一个对象中的属性拷贝到另一个对象中去
 * @parmas {Object} 需要被拷贝的对象
 * @parmas {Object} 可选,目标对象,如果不填直接返回一个对象
 */

function deepClone(origin, target = {}) {

    // 循环遍历对象的属性
    for (key in origin) {
        
        let isType = Object.prototype.toString.call(origin[key])

        // 克隆对象类型
        if (isType === '[object Object]') {
            target[key] = {}
            deepClone(origin[key], target[key])
            continue
        }

        // 克隆数组类型
         if (isType === '[object Array]') {
            target[key] = []
            deepClone(origin[key], target[key])
            continue
        }

        // 克隆 Set 类型
      
        // 克隆 Map 类型

        // 克隆其他类型

        // 克隆基础类型
        target[key] = origin[key]
    
    }

    return target
}

let zhu = {
  name: '朱昆鹏',
  technology: ['css', 'html', 'js'],
  girlfriend: {
    name: 'lyt'
  }
}

let zhuClone = deepClone(zhu) // zhuClone 内容完全和 zhu 一样

let zhuTest = { test: '测试' }
let zhuTestClone = deepClone(zhuTest, zhu) // zhuTestClone 不仅有 zhu所有内容,还有 zhuTest 的内容



// JSON.parse(JSON.stringify(obj) 方法进行拷贝,了解就行
const obj = {
  name:'axuebin',
  sayHello:function(){
    console.log('Hello World');
  }
}
console.log(JSON.parse(JSON.stringify(obj)); // {name: "axuebin"} ???
// undefined、function、symbol 会在转换过程中被忽略,所以就不能用这个方法进行深拷贝


// 浅拷贝
function clone(origin, target = {}) {
    let target = {};
    for (const key in origin) {
        target[key] = origin[key];
    }
    return target;
};

复制代码

3.拓展:首层浅拷贝


function shallowClone(source) {
  const targetObj = source.constructor === Array ? [] : {}; // 判断复制的目标是数组还是对象
  for (let keys in source) { // 遍历目标
    if (source.hasOwnProperty(keys)) {
      targetObj[keys] = source[keys];
    }
  }
  return targetObj;
}

const originObj = {
  a:'a',
  b:'b',
  c:[1, 2, 3],
  d:{ dd: 'dd' }
};

const cloneObj = shallowClone(originObj);
console.log(cloneObj === originObj); // false
cloneObj.a = 'aa';
cloneObj.c = [1, 1, 1];
cloneObj.d.dd = 'surprise';

console.log(cloneObj); // {a:'aa',b:'b',c:[1,1,1],d:{dd:'surprise'}}
console.log(originObj); // {a:'a',b:'b',c:[1,2,3],d:{dd:'surprise'}}

复制代码

4.判断对象是否为空对象


// 参考:https://www.cnblogs.com/HKCC/p/6083575.html

if (JSON.stringify(对象) === '{}') {
  console.log('空');
}

复制代码

5.判断对象中属性的个数

let obj = {name: '朱昆鹏', age: 21}

// ES6
Object.keys(obj).length // 2

// ES5
let attributeCount = obj => {
    let count = 0;
    for(let i in obj) {
        if(obj.hasOwnProperty(i)) {  // 建议加上判断,如果没有扩展对象属性可以不加
            count++;
        }
    }
    return count;
}

attributeCount(obj) // 2
复制代码

6.JS 对象转 url 查询字符串

const objectToQueryString = (obj) => Object.keys(obj).map((key) => `${encodeURIComponent(key)}=${encodeURIComponent(obj[key])}`).join('&');
objectToQueryString({name: 'Jhon', age: 18, address: 'beijing'})
// name=Jhon&age=18&address=beijing
复制代码

7.对象遍历

let objs = {
    1: {
        name: '朱昆鹏'
    },
    2: {
        name: '林雨桐'
    }
}

Object.keys(objs).forEach( ket => {
  console.log(key,objs[key])
})

// 1 {name: '朱昆鹏'} 2 {nama:'林雨桐'}

复制代码

🌴DOM

1.常用DOM接口


// 获取DOM节点
document.getElementById() // 通过ID获取
document.getElementsByTagName() // 标签名
document.getElementsByClassName() // 类名
document.querySelector() // 通过选择器获取一个元素
document.querySelectorAll() // 通过选择器获取一组元素
document.body // 获取body的方法
document.getElementsByName(name) // 通过name属性查找元素节点
document.documentElement // 获取html的方法

// 节点类型
元素节点(标签) // 属性nodeType返回值1
属性节点(标签里的属性)// 返回值2
文本节点 // 返回值3
注释节点(comment) // 返回值8
document // 返回值9
DocumentFragment // 返回值11

// 节点接口
dom元素.parentNode // 返回当前元素的父节点
dom元素.childNodes // 子节点们
dom元素.firstChild // 第一个子节点
dom元素.lastChild // 最后一个子节点
dom元素.nextSibling // 后一个兄弟节点 previousSibling -> 前一个兄弟节点

// 元素节点接口
dom元素.parentElement // 返回当前元素的父元素节点
dom元素.children // 返回当前元素的元素子节点
dom元素.firstElementChild // 第一个元素子节点(IE不兼容)
dom元素.lastElementChild // 最后一个元素子节点(IE不兼容)
dom元素.nextElementSibling // 返回后一个兄弟元素节点
dom元素.previousElementSibling // 返回前一个兄弟元素节点

// 节点的四个属性和一个方法
节点.nodeName // 元素的标签名,以大写形式表示(只读)
节点.nodeValue // Text节点或者Comment节点的文本内容,(读写)
节点.nodeType // 该节点的类型(只读)
节点.attributes // Element节点的属性集合
节点.hasChildNodes() // 判断节点 是否有子节点

// Element节点的 属性和方法
dom元素.innerHtml
dom元素.innerText
dom元素.attributes // 获取元素身上所有属性构成的集合
dom元素.setAttribute("属性名","属性值")// 给元素设置属性和属性值
dom元素.getAttribute("属性名")// 获取属性值的方法
dom元素.removerAttribute("属性") // 删除属性


// ============== 操作接口 ==================

// 增
document.createElement() // 创建元素节点
document.createTextNode() // 创建文本节点
document.creaetComment() //创建注释节点
document.createDocumentFragment() // 创建文档碎片节点

// 插
父元素节点.appendChild(子元素对象) // 在元素节点的子元素最后插入子元素
父元素节点.insertBefore(父元素中的子元素a, 需要插入的子元素b) // 最后的结果是,父元素节点中 b元素插入到了 a的前面

// 删
元素节点.remove() // 删除DOM元素(自己)
父元素节点.removeChild(子元素节点) // 删除子元素

// 替换
父元素节点.replaceChild(新的节点, 需要被替换的子节点)

// 复制
元素节点.cloneChild() // 返回值是 复制出来的节点

// 元素节点赋值 示例
dom元素.style.width = ...
dom元素.style.backgroundColor = ...
dom元素.className = ...

复制代码

2.判断当前位置是否为页面底部

function bottomVisible() {
  return document.documentElement.clientHeight + window.scrollY >= (document.documentElement.scrollHeight || document.documentElement.clientHeight)
}

bottomVisible() // 返回值为true/false
复制代码

3.全屏

1.进入全屏
function launchFullscreen(element) {
  if (element.requestFullscreen) {
    element.requestFullscreen()
  } else if (element.mozRequestFullScreen) {
    element.mozRequestFullScreen()
  } else if (element.msRequestFullscreen) {
    element.msRequestFullscreen()
  } else if (element.webkitRequestFullscreen) {
    element.webkitRequestFullScreen()
  }
}

launchFullscreen(document.documentElement) // 整个页面进入全屏
launchFullscreen(document.getElementById("id")) //某个元素进入全屏
复制代码
退出全屏
function exitFullscreen() {
  if (document.exitFullscreen) {
    document.exitFullscreen()
  } else if (document.msExitFullscreen) {
    document.msExitFullscreen()
  } else if (document.mozCancelFullScreen) {
    document.mozCancelFullScreen()
  } else if (document.webkitExitFullscreen) {
    document.webkitExitFullscreen()
  }
}

exitFullscreen()
复制代码
全屏事件
document.addEventListener("fullscreenchange", function (e) {
  if (document.fullscreenElement) {
    console.log('进入全屏')
  } else {
    console.log('退出全屏')
  }
})
复制代码

4.判断dom元素是否具有某个className

方法一:使用HTML5新增classList 来操作类名

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
</head>
<body>
  <div id="test" class="te"></div>

  <script>
    
    let div = document.getElementById('test')
    console.log(div.classList.contains("te")) // true

  </script>
</body>
</html>
复制代码

拓展:

  • classList.add(newClassName);添加新的类名,如已经存在,取消添加
  • classList.contains(oldClassName):确定元素中是否包含指定的类名,返回值为true,false
  • classList.remove(oldClassName):移除已经存在的类名;
  • classList.toggle(className):如果classList中存在给定的值,删除它,否则,添加它;

🦀感谢掘金用户tjNane分享此方法


方法二:

const  hasClass = (el, className) => new RegExp(`(^|\\s)${className}(\\s|$)`).test(el.className);
复制代码

🌱BOM

1.返回当前网页地址

function currentURL() {
  return window.location.href
}

currentURL() // "https://juejin.im/timeline"
复制代码

2.获取滚动条位置

function getScrollPosition(el = window) {
  return {
    x: (el.pageXOffset !== undefined) ? el.pageXOffset : el.scrollLeft,
    y: (el.pageYOffset !== undefined) ? el.pageYOffset : el.scrollTop
  }
}

getScrollPosition() // {x: 0, y: 692}
复制代码

3.获取url中的参数

function getURLParameters(url) {
  const params = url.match(/([^?=&]+)(=([^&]*))/g)
  return params?params.reduce(
    (a, v) => (a[v.slice(0, v.indexOf('='))] = v.slice(v.indexOf('=') + 1), a), {}
  ):[]
}

getURLParameters('http://www.baidu.com/index?name=tyler') // {name: "tyler"}
复制代码

4.检测设备类型

const detectDeviceType = () =>/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|OperaMini/i.test(navigator.userAgent) ? 'Mobile' : 'Desktop';

detectDeviceType() // "Desktop"
复制代码

🕰时间

1.Date 常用API

new Date() // 创建一个时间对象 Fri Jul 12 2019 19:59:59 GMT+0800 (中国标准时间)

// 返回自1970年1月1日 00:00:00 UTC到当前时间的毫秒数。
Date.now(); // 1562932828164

// 解析一个表示某个日期的字符串,并返回从1970-1-1 00:00:00 UTC 到该日期对象(该日期对象的UTC时间)的毫秒数
Date.parse('2019.7.12') // 1562860800000

// 年月日时分秒 获取
let dateMe = new Date()

dateMe.getFullYear() // 2019 | 根据本地时间返回指定日期的年份
dateMe.getMonth() // 6 | 根据本地时间,返回一个指定的日期对象的月份,为基于0的值(0表示一年中的第一月)。
dateMe.getDate() // 12 | 根据本地时间,返回一个指定的日期对象为一个月中的哪一日(从1--31)
dateMe.getHours() // 20 |根据本地时间,返回一个指定的日期对象的小时。
dateMe.getMinutes() // 11 | 根据本地时间,返回一个指定的日期对象的分钟数。
dateMe.getSeconds() // 29 | 方法根据本地时间,返回一个指定的日期对象的秒数
dateMe.getMilliseconds() // 363 | 根据本地时间,返回一个指定的日期对象的毫秒数。

dateMe.toJSON() // 🔥 "2019-07-12T12:05:15.363Z" | 返回 Date 对象的字符串形式
dateMe.getDay() // 5 | 根据本地时间,返回一个具体日期中一周的第几天,0 表示星期天(0 - 6)
dateMe.getTime() // 1562933115363 | 方法返回一个时间的格林威治时间数值。
dateMe.toString() // "Fri Jul 12 2019 20:05:15 GMT+0800 (中国标准时间)" | 返回一个字符串,表示该Date对象
dateMe.getTimezoneOffset() // -480(说明比正常时区慢480分钟,所以要加480分钟才对) | 返回协调世界时(UTC)相对于当前时区的时间差值,单位为分钟。
dateMe.toDateString() // "Fri Jul 12 2019" | 以美式英语和人类易读的形式返回一个日期对象日期部分的字符串。

复制代码

MDN 更多详细


2.一个时间戳格式的数字,是多少 天小时分钟秒毫秒

const formatDuration = ms => {
  if (ms < 0) ms = -ms;
  const time = {
    day: Math.floor(ms / 86400000),
    hour: Math.floor(ms / 3600000) % 24,
    minute: Math.floor(ms / 60000) % 60,
    second: Math.floor(ms / 1000) % 60,
    millisecond: Math.floor(ms) % 1000
  };
  return Object.entries(time)
    .filter(val => val[1] !== 0)
    .map(([key, val]) => `${val} ${key}${val !== 1 ? 's' : ''}`)
    .join(', ');
};

formatDuration(3161012); // 52 minutes, 41 seconds, 12 milliseconds
复制代码

3.格林尼治时间 转 北京时间(可传格林尼治时间 或者 时间戳)

function myTimeToLocal(inputTime){
	if(!inputTime && typeof inputTime !== 'number'){
		return '';
	}
	let localTime = '';
	inputTime = new Date(inputTime).getTime();
	const offset = (new Date()).getTimezoneOffset();
	localTime = (new Date(inputTime - offset * 60000)).toISOString();
	localTime = localTime.substr(0, localTime.lastIndexOf('.'));
	localTime = localTime.replace('T', ' ');
	return localTime;
}

console.log(myTimeToLocal(1530540726443)); // 2018-07-02 22:12:06
console.log(myTimeToLocal('2017-11-16T05:23:20.000Z')); // 2017-11-16 13:23:20
复制代码

4.获取两个日期相差天数

function getDaysDiffBetweenDates (dateInitial, dateFinal) {
    return (dateFinal - dateInitial) / (1000 * 3600 * 24);
}

getDaysDiffBetweenDates(new Date('2017-12-13'), new Date('2017-12-22')); // 9
复制代码

5.一个数组中,有时间,需要将这个数组按照时间进行排序

let data = [
{
  id: 1,
  publishTime: "2019-05-14 18:10:29"
},
{
  id: 2,
  publishTime: "2019-05-14 18:17:29"
},
{
  id: 3,
  publishTime: "2019-05-14 15:09:25"
}]

data.sort((a, b) => b.publishTime - a.publishTime);

// 0: {id: 2, publishTime: "2019-05-14 18:17:29"}
// 1: {id: 1, publishTime: "2019-05-14 18:10:29"}
// 2: {id: 3, publishTime: "2019-05-14 15:09:25"}

复制代码

💍处理JS原生具有的一些问题

1.加减法精度缺失问题

// 加法函数(因为JS小数计算 丢失精度)
function add(arg1, arg2) { 
    let r1, r2, m; 
    try { r1 = arg1.toString().split(".")[1].length } catch (e) { r1 = 0 } 
    try { r2 = arg2.toString().split(".")[1].length } catch (e) { r2 = 0 } 
    m = Math.pow(10, Math.max(r1, r2)) 
    return (arg1 * m + arg2 * m) / m 
}
复制代码
// 减法函数(因为JS小数计算 丢失精度)
function sub(arg1, arg2) { 
    let r1, r2, m, n; 
    try { r1 = arg1.toString().split(".")[1].length } catch (e) { r1 = 0 } 
    try { r2 = arg2.toString().split(".")[1].length } catch (e) { r2 = 0 } 
    m = Math.pow(10, Math.max(r1, r2)); 
    n = (r1 >= r2) ? r1 : r2; 
    return Number(((arg1 * m - arg2 * m) / m).toFixed(n)); 
}
复制代码

2.递归优化(尾递归)

// 尾递归函数 摘自阮一峰ES6 | 自己懒得写了
function tco(f) {
  let value;
  let active = false;
  let accumulated = [];

  return function accumulator() {
    accumulated.push(arguments);
    if (!active) {
      active = true;
      while (accumulated.length) {
        value = f.apply(this, accumulated.shift());
      }
      active = false;
      return value;
    }
  };
}

// 使用
新的函数 = tco(递归函数)

复制代码

🙏其他

1.Math函数的一些应用

parseInt(5.12) // 5 | 只保留整数部分(丢弃小数部分)
Math.floor(5.12) // 5 | 向下取整(效果和parseInt一样)
Math.ceil(5.12) // 6 | 向上取整(有小数,整数就+1)

Math.round(5.499) // 5 | 四舍五入
Math.round(5.501) // 6 | 四舍五入

Math.abs(-5) // 5 | 绝对值

Math.max(5, 6) // 6 | 返回两者中较大的数
Math.min(5, 6) // 5 | 返回两者中较小的数

Math.random() // 随机数 (0-1)
复制代码

2.常用正则速查

消除字符串首尾两端的空格(替换)

let reg = /^\s+|\s+$/g;

let str = ' #id div.class '; 
str.replace(reg, '') // "#id div.class"
复制代码

*把手机号码替换成 (替换)

var reg = /1[24578]\d{9}/;

var str = '姓名:朱昆鹏 手机:15932638907'; // 手记号瞎写的
str.replace(reg, '***') //"姓名:朱昆鹏 手机:***"
复制代码

替换敏感字(替换)

let str = '中国中国人民解放军中华人民共和国';
    
let r = str.replace(/中国|军/g, input => {
    let t = '';
    for (let i = 0; i<input.length; i++) {
        t += '*';
    }
    return t;
})
     
console.log(r); //****人民解放*中华人民共和国   
复制代码

千位分隔符(替换)

let reg = /(\d)(?=(?:\d{3})+$)/g

let str = '100002003232322';    
let r = str.replace(, '$1,'); //100,002,003,232,322
复制代码

匹配网页标签(匹配)

var reg = /<(.+)>.+<\/\1>/;

var str = '朱昆鹏<div>2707509@.qq.com</div>朱昆鹏';    
str.match(reg); // ["<div>2707509@.qq.com</div>"]
复制代码

验证手记号(验证)

let reg = /^1((3[\d])|(4[5,6,9])|(5[0-3,5-9])|(6[5-7])|(7[0-8])|(8[1-3,5-8])|(9[1,8,9]))\d{8}$/;

reg.test('15932539095'); //true
reg.test('234554568997'); //false
复制代码

验证邮箱地址(验证)

let reg = /^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/

reg.test('2775033@hotmail.com'); //true
reg.test('abc@'); //false
复制代码

验证身份证(验证)

let reg = /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/

reg.test('31210119651230518X'); //true 自己瞎写的
reg.test('2101196523s230518X'); //false 自己瞎写的
复制代码

验证中国邮箱编码(验证)

let reg = /^(0[1-7]|1[0-356]|2[0-7]|3[0-6]|4[0-7]|5[1-7]|6[1-7]|7[0-5]|8[013-6])\d{4}$/

reg.test('065900'); //true
reg.test('999999'); //false
复制代码

验证ipv4地址正则(验证)

let reg = /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/

reg.test('192.168.1.192'); //true
reg.test('127.0.0.1s'); //false
复制代码

验证银行卡号(16或19位)

let reg = /^([1-9]{1})(\d{15}|\d{18})$/

reg.test('6222026006705354218') // true
复制代码

验证中文姓名(验证)

let reg = /^([\u4e00-\u9fa5\·]{2,10})$/

reg.test('朱昆鹏'); //true
reg.test('Zhu Kunpeng'); //false
复制代码

3.变换变量


// [letA,letB] = [letB,letA];

let a = 1;
let b = 2;
[a, b] = [b, a] // a = 2 b = 1

复制代码

4.格式化对象为JSON代码

const formatted = JSON.stringify({name: 'Jhon', age: 18, address: 'sz'}, null, 4);
/*
{
    "name": "Jhon",
    "age": 18,
    "address": "sz"
}
*/

// 该字符串化命令有三个参数。第一个是Javascript对象。第二个是可选函数,可用于在JSON进行字符串化时对其执行操作。最后一个参数指示要添加多少空格作为缩进以格式化JSON。省略最后一个参数,JSON将返回一个长行。如果myObj中存在循环引用,则会格式失败。
复制代码

5.随机生成六位数字验证码

const code = Math.floor(Math.random() * 1000000).toString().padStart(6, "0") // 942377
复制代码

6.RGB 颜色转 16进制颜色

const RGBToHex = (r, g, b) => ((r << 16) + (g << 8) + b).toString(16).padStart(6, '0');
RGBToHex(255, 165, 1); // 'ffa501'
复制代码

7.生成随机整数

function randomNum(min, max) {
  switch (arguments.length) {
    case 1:
      return parseInt(Math.random() * min + 1, 10)
    case 2:
      return parseInt(Math.random() * (max - min + 1) + min, 10)
    default:
      return 0
  }
}

randomNum(1,10) // 随机 [1,10]的整数
复制代码

8.去除空格(1-所有空格 2-前后空格 3-前空格 4-后空格 默认为1)


/**
 * trim 去除空格
 * param1  string str 待处理字符串
 * param2  number type 去除空格类型 1-所有空格  2-前后空格  3-前空格 4-后空格 默认为1
 * return  string str 处理后的字符串
 */
function trim(str, type = 1) {
    if (type && type !== 1 && type !== 2 && type !== 3 && type !== 4) return;
    switch (type) {
        case 1:
            return str.replace(/\s/g, "");
        case 2:
            return str.replace(/(^\s)|(\s*$)/g, "");
        case 3:
            return str.replace(/(^\s)/g, "");
        case 4:
            return str.replace(/(\s$)/g, "");
        default:
            return str;
    }
}

复制代码

9.大小写转换


/**
 * 大小写转换
 * param1 string str 待转换的字符串
 * param2 number type 1-全大写 2-全小写 3-首字母大写 
 * return  string str 处理后的字符串
 */

function turnCase(str, type) {
    switch (type) {
        case 1:
            return str.toUpperCase()
        case 2:
            return str.toLowerCase();
        case 3:
            return str[0].toUpperCase() + str.substr(1).toLowerCase()
        default:
            return str;
    }
}

复制代码

10.随机16进制颜色 hexColor

/**
 * 随机16进制颜色 hexColor
 * return  string str 带#号的随机16进制颜色
 */

function hexColor() {

    let str = '#';
    let arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 'A', 'B', 'C', 'D', 'E', 'F'];
    for (let i = 0; i < 6; i++) {
        let index = Number.parseInt(Math.random() * 16);
        str += arr[index]
    }
    return str;
}
复制代码

11.统计一段文字中指定文字出现次数 keywordsCount(骚操作)

/**
 * 关键词统计:统计一段文字中指定文字出现次数 keywordsCount
 * param1 string text 进行统计的文本
 * param2 string keywords 进行统计的关键词
 * return number count 关键词出现次数
 * tip:param1 document.body.innerText--全文统计
 */

function keywordsCount(text, keywords) {
    return text.split(keywords).length - 1
}

复制代码

12.好的笔记文章


13. 轮询等待函数

/**
 * 轮询等待函数
 * 
 * @param {Function} 轮询结束的条件
 * @param {Function} 成功之后的回调函数
 * @param {Number} 轮询时间(默认100ms)
 * @param {Number} 轮询最长的时间(默认1000ms)
 */
function pollingWaiting (callBack, resCallBack, time = 100, lastTime = 1000) {
  
  let startTime = Date.now()
  let t = null;
  let fn =  function () {
      t = setTimeout(() => {
          if (!callBack()) {
              // 此处可以采用尾递归优化,来防止占用过多内存
              console.log('startTime', Date.now() - startTime > lastTime)
              (Date.now() - startTime > lastTime) ? window.clearInterval(t) : fn()
          } else {
              resCallBack()
          }
      }, time);
  }
  fn()
}

// 示例
let a = 1;
setTimeout( () => {
  a = 2
}, 500)

pollingWaiting( () => {
  return a === 2
}, () => {
  console.log('触发了', a)
}, 100, 800)

// 4 startTime false
// 触发了 2
复制代码

14.大数值转换为万,亿

/**
 * 大数值转换为万,亿函数
 * 
 * @param {Number} 大数
 * @param {Number} 保留几位小数
 */
function numConversion (num, point = 2) {

  let numStr = num.toString().split('.')[0] // 去掉小数点后的数值字符串
  let numLen = numStr.length

  if (numLen < 6) {
    return numStr
  } else if (numLen >= 6 && numLen <= 8) {
    let decimal = numStr.substring(numLen - 4, numLen - 4 + point)
    let res = parseInt(num / 10000) + '.' + decimal + '万'
    return res
  } else if (numLen > 8) {
    let decimal = numStr.substring(numLen - 8, numLen - 8 + point)
    let res = parseInt(num / 100000000) + '.' + decimal + '亿'
    return res
  }
}

numConversion(12345) // 12345
numConversion(1234567) // 123.45万
numConversion(123456789) // 1.23亿
复制代码

15.常见的XSS转义场景

// 转义HTML特殊字符
function HtmlEncode(str) {
    var hex = new Array('0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f');
    var preescape = str;
    var escaped = "";
    for(var i = 0; i < preescape.length; i++){
        var p = preescape.charAt(i);
        escaped = escaped + escapeCharx(p);
    }
    
    return escaped;
                    
    function escapeCharx(original){
        var found=true;
        var thechar=original.charCodeAt(0);
        switch(thechar) {
            case 10: return "<br/>"; break; //newline
            case 32: return "&nbsp;"; break; //space
            case 34:return "&quot;"; break; //"
            case 38:return "&amp;"; break; //&
            case 39:return "&#x27;"; break; //'
            case 47:return "&#x2F;"; break; // /
            case 60:return "&lt;"; break; //<
            case 62:return "&gt;"; break; //>
            case 198:return "&AElig;"; break;
            case 193:return "&Aacute;"; break;
            case 194:return "&Acirc;"; break; 
            case 192:return "&Agrave;"; break; 
            case 197:return "&Aring;"; break; 
            case 195:return "&Atilde;"; break; 
            case 196:return "&Auml;"; break; 
            case 199:return "&Ccedil;"; break; 
            case 208:return "&ETH;"; break;
            case 201:return "&Eacute;"; break; 
            case 202:return "&Ecirc;"; break; 
            case 200:return "&Egrave;"; break; 
            case 203:return "&Euml;"; break;
            case 205:return "&Iacute;"; break;
            case 206:return "&Icirc;"; break; 
            case 204:return "&Igrave;"; break; 
            case 207:return "&Iuml;"; break;
            case 209:return "&Ntilde;"; break; 
            case 211:return "&Oacute;"; break;
            case 212:return "&Ocirc;"; break; 
            case 210:return "&Ograve;"; break; 
            case 216:return "&Oslash;"; break; 
            case 213:return "&Otilde;"; break; 
            case 214:return "&Ouml;"; break;
            case 222:return "&THORN;"; break; 
            case 218:return "&Uacute;"; break; 
            case 219:return "&Ucirc;"; break; 
            case 217:return "&Ugrave;"; break; 
            case 220:return "&Uuml;"; break; 
            case 221:return "&Yacute;"; break;
            case 225:return "&aacute;"; break; 
            case 226:return "&acirc;"; break; 
            case 230:return "&aelig;"; break; 
            case 224:return "&agrave;"; break; 
            case 229:return "&aring;"; break; 
            case 227:return "&atilde;"; break; 
            case 228:return "&auml;"; break; 
            case 231:return "&ccedil;"; break; 
            case 233:return "&eacute;"; break;
            case 234:return "&ecirc;"; break; 
            case 232:return "&egrave;"; break; 
            case 240:return "&eth;"; break; 
            case 235:return "&euml;"; break; 
            case 237:return "&iacute;"; break; 
            case 238:return "&icirc;"; break; 
            case 236:return "&igrave;"; break; 
            case 239:return "&iuml;"; break; 
            case 241:return "&ntilde;"; break; 
            case 243:return "&oacute;"; break;
            case 244:return "&ocirc;"; break; 
            case 242:return "&ograve;"; break; 
            case 248:return "&oslash;"; break; 
            case 245:return "&otilde;"; break;
            case 246:return "&ouml;"; break; 
            case 223:return "&szlig;"; break; 
            case 254:return "&thorn;"; break; 
            case 250:return "&uacute;"; break; 
            case 251:return "&ucirc;"; break; 
            case 249:return "&ugrave;"; break; 
            case 252:return "&uuml;"; break; 
            case 253:return "&yacute;"; break; 
            case 255:return "&yuml;"; break;
            case 162:return "&cent;"; break; 
            case '\r': break;
            default:
                found=false;
                break;
        }
        if(!found){
            if(thechar>127) {
                var c=thechar;
                var a4=c%16;
                c=Math.floor(c/16); 
                var a3=c%16;
                c=Math.floor(c/16);
                var a2=c%16;
                c=Math.floor(c/16);
                var a1=c%16;
                return "&#x"+hex[a1]+hex[a2]+hex[a3]+hex[a4]+";";        
            }
            else{
                return original;
            }
        }    
    }
}

// 转义JS特殊字符
function JavaScriptEncode(str) 
     
    var hex=new Array('0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f');
        
    function changeTo16Hex(charCode){
        return "\\x" + charCode.charCodeAt(0).toString(16);
    }
    
    function encodeCharx(original) {
        
        var found = true;
        var thecharchar = original.charAt(0);
        var thechar = original.charCodeAt(0);
        switch(thecharchar) {
            case '\n': return "\\n"; break; //newline
            case '\r': return "\\r"; break; //Carriage return
            case '\'': return "\\'"; break;
            case '"': return "\\\""; break;
            case '\&': return "\\&"; break;
            case '\\': return "\\\\"; break;
            case '\t': return "\\t"; break;
            case '\b': return "\\b"; break;
            case '\f': return "\\f"; break;
            case '/': return "\\x2F"; break;
            case '<': return "\\x3C"; break;
            case '>': return "\\x3E"; break;
            default:
                found=false;
                break;
        }
        if(!found){
            if(thechar > 47 && thechar < 58){ //数字
                return original;
            }
            
            if(thechar > 64 && thechar < 91){ //大写字母
                return original;
            }

            if(thechar > 96 && thechar < 123){ //小写字母
                return original;
            }        
            
            if(thechar>127) { //大于127用unicode
                var c = thechar;
                var a4 = c%16;
                c = Math.floor(c/16); 
                var a3 = c%16;
                c = Math.floor(c/16);
                var a2 = c%16;
                c = Math.floor(c/16);
                var a1 = c%16;
                return "\\u"+hex[a1]+hex[a2]+hex[a3]+hex[a4]+"";        
            }
            else {
                return changeTo16Hex(original);
            }
            
        }
    }     
  
    var preescape = str;
    var escaped = "";
    var i=0;
    for(i=0; i < preescape.length; i++){
        escaped = escaped + encodeCharx(preescape.charAt(i));
    }
    return escaped;
}
复制代码

📚参考列表

关注下面的标签,发现更多相似文章
评论