编程技术文章分享与教程

网站首页 > 技术文章 正文

细品269个JavaScript小函数,让你少加班熬夜(三)「值得收藏」

hmc789 2024-11-13 11:29:03 技术文章 1 ℃


作者:叫我詹躲躲

转发链接:https://juejin.im/post/5edb6c6be51d4578a2555a9b

前言

细品269个JavaScript小函数,让你少加班熬夜(一)「值得收藏」

细品269个JavaScript小函数,让你少加班熬夜(二)「值得收藏」

细品269个JavaScript小函数,让你少加班熬夜(三)「值得收藏」(本篇)

细品269个JavaScript小函数,让你少加班熬夜(四)「值得收藏」

细品269个JavaScript小函数,让你少加班熬夜(五)「值得收藏」

细品269个JavaScript小函数,让你少加班熬夜(六)「值得收藏」

131.file转base64

 /**
     * @param { * } file 图片文件
       */
       export const fileToBase64 = file => {
       let reader = new FileReader();
       reader.readAsDataURL(file);
   reader.onload = function (e) {
        return e.target.result
    };
    };
复制代码

132.递归生成树形结构

export function getTreeData(data, pid, pidName = 'parentId', idName = 'id', childrenName = 'children', key) {
    let arr = [];

    for (let i = 0; i < data.length; i++) {
        if (data[i][pidName] == pid) {
            data[i].key = data[i][idName];
            data[i][childrenName] = getTreeData(data, data[i][idName], pidName, idName, childrenName);
            arr.push(data[i]);
        }
    }
    
    return arr;

}
复制代码

133.遍历树节点

export function foreachTree(data, childrenName = 'children', callback) {
    for (let i = 0; i < data.length; i++) {
        callback(data[i]);
        if (data[i][childrenName] && data[i][childrenName].length > 0) {
            foreachTree(data[i][childrenName], childrenName, callback);
        }
    }
}
复制代码

134.追溯父节点

export function traceParentNode(pid, data, rootPid, pidName = 'parentId', idName = 'id', childrenName = 'children') {
    let arr = [];
    foreachTree(data, childrenName, (node) => {
        if (node[idName] == pid) {
            arr.push(node);
            if (node[pidName] != rootPid) {
                arr = arr.concat(traceParentNode(node[pidName], data, rootPid, pidName, idName));
            }
        }
    });
    return arr; 
}
复制代码

135.寻找所有子节点

export function traceChildNode(id, data, pidName = 'parentId', idName = 'id', childrenName = 'children') {
    let arr = [];
    foreachTree(data, childrenName, (node) => {
        if (node[pidName] == id) {
            arr.push(node);
            arr = arr.concat(traceChildNode(node[idName], data, pidName, idName, childrenName));
        }
    });
    return arr;
}
复制代码

136.根据pid生成树形结构

/**
    *  @param { object } items 后台获取的数据
*  @param { * } id 数据中的id
 *  @param { * } link 生成树形结构的依据
    */
    export const createTree = (items, id = null, link = 'pid') =>{
    items.filter(item => item[link] === id).map(item => ({ ...item, children: createTree(items, item.id) }));
    };
复制代码

137.查询数组中是否存在某个元素并返回元素第一次出现的下标

 /** 
     * @param {*} item 
     * @param { array } data
       */
       export function inArray(item, data) {
       for (let i = 0; i < data.length; i++) {
           if (item === data[i]) {
           return i;
        }
    }
    return -1;
    }
复制代码

138.Windows根据详细版本号判断当前系统名称

 /**
     * @param { string } osVersion 
       */
       export function OutOsName(osVersion) {
       if(!osVersion){
           return
       }
       let str = osVersion.substr(0, 3);
       if (str === "5.0") {
           return "Win 2000"
       } else if (str === "5.1") {
           return "Win XP"
       } else if (str === "5.2") {
           return "Win XP64"
       } else if (str === "6.0") {
           return "Win Vista"
       } else if (str === "6.1") {
           return "Win 7"
       } else if (str === "6.2") {
           return "Win 8"
       } else if (str === "6.3") {
           return "Win 8.1"
       } else if (str === "10.") {
           return "Win 10"
   } else {
        return "Win"
    }
    }
复制代码

139.判断手机是Andoird还是IOS

/**
    *  0: ios
    *  1: android
    *  2: 其它
       */
       export function getOSType() {
       let u = navigator.userAgent, app = navigator.appVersion;
       let isAndroid = u.indexOf('Android') > -1 || u.indexOf('Linux') > -1;
       let isIOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/);
       if (isIOS) {
           return 0;
   }
    if (isAndroid) {
        return 1;
    }
    return 2;
    }
复制代码

140.函数防抖

 /**
     * @param { function } func
    
     * @param { number } wait 延迟执行毫秒数
    
 * @param { boolean } immediate  true 表立即执行,false 表非立即执行
       */
       export function debounce(func,wait,immediate) {
       let timeout;
       return function () {
           let context = this;
           let args = arguments;
    
           if (timeout) clearTimeout(timeout);
           if (immediate) {
               let callNow = !timeout;
               timeout = setTimeout(() => {
                   timeout = null;
               }, wait);
               if (callNow) func.apply(context, args)
       }
        else {
            timeout = setTimeout(() => {
                func.apply(context, args)
            }, wait);
        }
 
    }
    }
复制代码

145.函数节流

 /**
     * @param { function } func 函数
    
     * @param { number } wait 延迟执行毫秒数
    
     * @param { number } type 1 表时间戳版,2 表定时器版
       */
       export function throttle(func, wait ,type) {
       let previous, timeout;
       if(type===1){
           previous = 0;
       }else if(type===2){
       timeout = null;
       }
       return function() {
           let context = this;
           let args = arguments;
           if(type===1){
               let now = Date.now();
    
               if (now - previous > wait) {
                   func.apply(context, args);
                   previous = now;
               }
           }else if(type===2){
           if (!timeout) {
                   timeout = setTimeout(() => {
                   timeout = null;
                    func.apply(context, args)
                }, wait)
            }
        }
 
    }
    }
复制代码

146.判断数据类型

 /**
     * @param {*} target 
       */
       export function type(target) {
       let ret = typeof(target);
       let template = {
           "[object Array]": "array",
           "[object Object]":"object",
           "[object Number]":"number - object",
       "[object Boolean]":"boolean - object",
           "[object String]":'string-object'
       };
    
       if(target === null) {
           return 'null';
       }else if(ret == "object"){
           let str = Object.prototype.toString.call(target);
           return template[str];
   }else{
        return ret;
    }
    }
复制代码

147.生成指定范围随机数

 /**
  * @param { number } min 
  * @param { number } max 
    */
    export const RandomNum = (min, max) => Math.floor(Math.random() * (max - min + 1)) + min;
复制代码

148.数组乱序

 /**
     * @param {array} arr
       */
       export function arrScrambling(arr) {
       let array = arr;
       let index = array.length;
       while (index) {
           index -= 1;
           let randomIndex = Math.floor(Math.random() * index);
           let middleware = array[index];
           array[index] = array[randomIndex];
       array[randomIndex] = middleware
    }
    return array
    }
复制代码

150.数组交集

 /**
  * @param { array} arr1
  * @param { array } arr2
    */
    export const similarity = (arr1, arr2) => arr1.filter(v => arr2.includes(v));
复制代码

151.数组中某元素出现的次数

 /**

     * @param { array } arr
 * @param {*} value
    */
    export function countOccurrences(arr, value) {
    return arr.reduce((a, v) => v === value ? a + 1 : a + 0, 0);
    }
复制代码

152.加法函数(精度丢失问题)

 /**
     * @param { number } arg1
     * @param { number } arg2
       */
       export 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
    }
复制代码

153.减法函数(精度丢失问题)

 /**
     * @param { number } arg1
     * @param { number } arg2
       */
       export 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));
    }
复制代码

154.除法函数(精度丢失问题)

 /**
     * @param { number } num1
     * @param { number } num2
       */
       export function division(num1,num2){
       let t1,t2,r1,r2;
       try{
           t1 = num1.toString().split('.')[1].length;
       }catch(e){
           t1 = 0;
       }
       try{
           t2=num2.toString().split(".")[1].length;
       }catch(e){
           t2=0;
   }
    r1=Number(num1.toString().replace(".",""));
    r2=Number(num2.toString().replace(".",""));
    return (r1/r2)*Math.pow(10,t2-t1);
    }
复制代码

155.乘法函数(精度丢失问题)

 /**
     * @param { number } num1
     * @param { number } num2
       */
       export function mcl(num1,num2){
   let m=0,s1=num1.toString(),s2=num2.toString();
    try{m+=s1.split(".")[1].length}catch(e){}
    try{m+=s2.split(".")[1].length}catch(e){}
    return Number(s1.replace(".",""))*Number(s2.replace(".",""))/Math.pow(10,m);
    }
复制代码

156.递归优化(尾递归)

 /**
     * @param { function } f
       */
       export 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;
        }
    };
    }
复制代码

157.生成随机整数

export function randomNumInteger(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
    }
}
复制代码

158.去除空格

 /**
     * @param { string } str 待处理字符串
     * @param  { number } type 去除空格类型 1-所有空格  2-前后空格  3-前空格 4-后空格 默认为1
       */
       export 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;
    }
    }
复制代码

159.大小写转换

/**
 * @param { string } str 待转换的字符串
 * @param { number } type 1-全大写 2-全小写 3-首字母大写 其他-不转换
   */

export 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;
    }
}
复制代码

160.随机16进制颜色 hexColor

 /**
 * 方法一
       */
       export 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).toString());
       str += arr[index]
    }
    return str;
    }
复制代码

161.随机16进制颜色 randomHexColorCode

 /**
     * 方法二
       */
   export const randomHexColorCode = () => {
    let n = (Math.random() * 0xfffff * 1000000).toString(16);
    return '#' + n.slice(0, 6);
    };
复制代码

162.转义html(防XSS攻击)

export const escapeHTML = str =>{
    str.replace(
        /[&<>'"]/g,
        tag =>
            ({
                '&': '&',
                '<': '<',
                '>': '>',
                "'": ''',
                '"': '"'
            }[tag] || tag)
    );
};
复制代码

163.检测移动/PC设备

export const detectDeviceType = () => { return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) ? 'Mobile' : 'Desktop'; };
复制代码

164.隐藏所有指定标签

 /**
  * 例: hide(document.querySelectorAll('img'))
    */
    export const hideTag = (...el) => [...el].forEach(e => (e.style.display = 'none'));
复制代码

165.返回指定元素的生效样式

 /**
  * @param { element} el  元素节点
  * @param { string } ruleName  指定元素的名称
    */
    export const getStyle = (el, ruleName) => getComputedStyle(el)[ruleName];
复制代码

166.检查是否包含子元素

 /**
  * @param { element } parent
  * @param { element } child
  * 例:elementContains(document.querySelector('head'), document.querySelector('title')); // true
    */
    export const elementContains = (parent, child) => parent !== child && parent.contains(child);
复制代码

167.数字超过规定大小加上加号“+”,如数字超过99显示99+

 /**
     * @param { number } val 输入的数字
     * @param { number } maxNum 数字规定界限
       */
       export const outOfNum = (val, maxNum) =>{
       val = val ? val-0 :0;
       if (val > maxNum ) {
       return `${maxNum}+`
    }else{
        return val;
    }
    };
复制代码

168.如何隐藏所有指定的元素

 const hide = (el) => Array.from(el).forEach(e => (e.style.display = 'none'));

 // 事例:隐藏页面上所有`<img>`元素?
 hide(document.querySelectorAll('img'))
复制代码

169.如何检查元素是否具有指定的类?

页面DOM里的每个节点上都有一个classList对象,程序员可以使用里面的方法新增、删除、修改节点上的CSS类。使用classList,程序员还可以用它来判断某个节点是否被赋予了某个CSS类。

 const hasClass = (el, className) => el.classList.contains(className)

 // 事例
 hasClass(document.querySelector('p.special'), 'special') // true
复制代码

170.如何切换一个元素的类?

 const toggleClass = (el, className) => el.classList.toggle(className)

 // 事例 移除 p 具有类`special`的 special 类
 toggleClass(document.querySelector('p.special'), 'special')

171.如何获取当前页面的滚动位置?

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

 // 事例
 getScrollPosition(); // {x: 0, y: 200}
复制代码

172.如何平滑滚动到页面顶部

 const scrollToTop = () => {
   const c = document.documentElement.scrollTop || document.body.scrollTop;
   if (c > 0) {
     window.requestAnimationFrame(scrollToTop);
     window.scrollTo(0, c - c / 8);
   }
 }

 // 事例
 scrollToTop()
复制代码
window.requestAnimationFrame() 告诉浏览器——你希望执行一个动画,并且要求浏览器在下次重绘之前调用指定的回调函数更新动画。该方法需要传入一个回调函数作为参数,该回调函数会在浏览器下一次重绘之前执行。
 requestAnimationFrame:优势:由系统决定回调函数的执行时机。60Hz的刷新频率,那么每次刷新的间隔中会执行一次回调函数,不会引起丢帧,不会卡顿。

window.requestAnimationFrame() 告诉浏览器——你希望执行一个动画,并且要求浏览器在下次重绘之前调用指定的回调函数更新动画。该方法需要传入一个回调函数作为参数,该回调函数会在浏览器下一次重绘之前执行。
 requestAnimationFrame:优势:由系统决定回调函数的执行时机。60Hz的刷新频率,那么每次刷新的间隔中会执行一次回调函数,不会引起丢帧,不会卡顿。
复制代码

173.如何检查父元素是否包含子元素?

 const elementContains = (parent, child) => parent !== child && parent.contains(child);

 // 事例
 elementContains(document.querySelector('head'), document.querySelector('title')); 
 // true
 elementContains(document.querySelector('body'), document.querySelector('body')); 
 // false
复制代码

174.如何检查指定的元素在视口中是否可见?

 const elementIsVisibleInViewport = (el, partiallyVisible = false) => {
   const { top, left, bottom, right } = el.getBoundingClientRect();
   const { innerHeight, innerWidth } = window;
   return partiallyVisible
     ? ((top > 0 && top < innerHeight) || (bottom > 0 && bottom < innerHeight)) &&
         ((left > 0 && left < innerWidth) || (right > 0 && right < innerWidth))
     : top >= 0 && left >= 0 && bottom <= innerHeight && right <= innerWidth;
 };

 // 事例
 elementIsVisibleInViewport(el); // 需要左右可见
 elementIsVisibleInViewport(el, true); // 需要全屏(上下左右)可以见
复制代码

175.如何获取元素中的所有图像?

 const getImages = (el, includeDuplicates = false) => {
   const images = [...el.getElementsByTagName('img')].map(img => img.getAttribute('src'));
   return includeDuplicates ? images : [...new Set(images)];
 };

 // 事例:includeDuplicates 为 true 表示需要排除重复元素
 getImages(document, true); // ['image1.jpg', 'image2.png', 'image1.png', '...']
 getImages(document, false); // ['image1.jpg', 'image2.png', '...']

本篇未完结,请继续下一篇

推荐JavaScript经典实例学习资料文章

细品269个JavaScript小函数,让你少加班熬夜(一)「值得收藏」

细品269个JavaScript小函数,让你少加班熬夜(二)「值得收藏」

深入JavaScript教你内存泄漏如何防范

手把手教你7个有趣的JavaScript 项目-上「附源码」

手把手教你7个有趣的JavaScript 项目-下「附源码」

JavaScript 使用 mediaDevices API 访问摄像头自拍

手把手教你前端代码如何做错误上报「JS篇」

一文让你彻底搞懂移动前端和Web 前端区别在哪里

63个JavaScript 正则大礼包「值得收藏」

提高你的 JavaScript 技能10 个问答题

JavaScript图表库的5个首选

一文彻底搞懂JavaScript 中Object.freeze与Object.seal的用法

可视化的 JS:动态图演示 - 事件循环 Event Loop的过程

教你如何用动态规划和贪心算法实现前端瀑布流布局「实践」

可视化的 js:动态图演示 Promises & Async/Await 的过程

原生JS封装拖动验证滑块你会吗?「实践」

如何实现高性能的在线 PDF 预览

细说使用字体库加密数据-仿58同城

Node.js要完了吗?

Pug 3.0.0正式发布,不再支持 Node.js 6/8

纯JS手写轮播图(代码逻辑清晰,通俗易懂)

JavaScript 20 年 中文版之创立标准

值得收藏的前端常用60余种工具方法「JS篇」

箭头函数和常规函数之间的 5 个区别

通过发布/订阅的设计模式搞懂 Node.js 核心模块 Events

「前端篇」不再为正则烦恼

「速围」Node.js V14.3.0 发布支持顶级 Await 和 REPL 增强功能

深入细品浏览器原理「流程图」

JavaScript 已进入第三个时代,未来将何去何从?

前端上传前预览文件 image、text、json、video、audio「实践」

深入细品 EventLoop 和浏览器渲染、帧动画、空闲回调的关系

推荐13个有用的JavaScript数组技巧「值得收藏」

前端必备基础知识:window.location 详解

不要再依赖CommonJS了

犀牛书作者:最该忘记的JavaScript特性

36个工作中常用的JavaScript函数片段「值得收藏」

Node + H5 实现大文件分片上传、断点续传

一文了解文件上传全过程(1.8w字深度解析)「前端进阶必备」

【实践总结】关于小程序挣脱枷锁实现批量上传

手把手教你前端的各种文件上传攻略和大文件断点续传

字节跳动面试官:请你实现一个大文件上传和断点续传

谈谈前端关于文件上传下载那些事【实践】

手把手教你如何编写一个前端图片压缩、方向纠正、预览、上传插件

最全的 JavaScript 模块化方案和工具

「前端进阶」JS中的内存管理

JavaScript正则深入以及10个非常有意思的正则实战

前端面试者经常忽视的一道JavaScript 面试题

一行JS代码实现一个简单的模板字符串替换「实践」

JS代码是如何被压缩的「前端高级进阶」

前端开发规范:命名规范、html规范、css规范、js规范

【规范篇】前端团队代码规范最佳实践

100个原生JavaScript代码片段知识点详细汇总【实践】

关于前端174道 JavaScript知识点汇总(一)

关于前端174道 JavaScript知识点汇总(二)

关于前端174道 JavaScript知识点汇总(三)

几个非常有意思的javascript知识点总结【实践】

都2020年了,你还不会JavaScript 装饰器?

JavaScript实现图片合成下载

70个JavaScript知识点详细总结(上)【实践】

70个JavaScript知识点详细总结(下)【实践】

开源了一个 JavaScript 版敏感词过滤库

送你 43 道 JavaScript 面试题

3个很棒的小众JavaScript库,你值得拥有

手把手教你深入巩固JavaScript知识体系【思维导图】

推荐7个很棒的JavaScript产品步骤引导库

Echa哥教你彻底弄懂 JavaScript 执行机制

一个合格的中级前端工程师需要掌握的 28 个 JavaScript 技巧

深入解析高频项目中运用到的知识点汇总【JS篇】

JavaScript 工具函数大全【新】

从JavaScript中看设计模式(总结)

身份证号码的正则表达式及验证详解(JavaScript,Regex)

浏览器中实现JavaScript计时器的4种创新方式

Three.js 动效方案

手把手教你常用的59个JS类方法

127个常用的JS代码片段,每段代码花30秒就能看懂-【上】

深入浅出讲解 js 深拷贝 vs 浅拷贝

手把手教你JS开发H5游戏【消灭星星】

深入浅出讲解JS中this/apply/call/bind巧妙用法【实践】

手把手教你全方位解读JS中this真正含义【实践】

书到用时方恨少,一大波JS开发工具函数来了

干货满满!如何优雅简洁地实现时钟翻牌器(支持JS/Vue/React)

手把手教你JS 异步编程六种方案【实践】

让你减少加班的15条高效JS技巧知识点汇总【实践】

手把手教你JS开发H5游戏【黄金矿工】

手把手教你JS实现监控浏览器上下左右滚动

JS 经典实例知识点整理汇总【实践】

2.6万字JS干货分享,带你领略前端魅力【基础篇】

2.6万字JS干货分享,带你领略前端魅力【实践篇】

简单几步让你的 JS 写得更漂亮

恭喜你获得治疗JS this的详细药方

谈谈前端关于文件上传下载那些事【实践】

面试中教你绕过关于 JavaScript 作用域的 5 个坑

Jquery插件(常用的插件库)

【JS】如何防止重复发送ajax请求

JavaScript+Canvas实现自定义画板

Continuation 在 JS 中的应用「前端篇」

作者:叫我詹躲躲

转发链接:https://juejin.im/post/5edb6c6be51d4578a2555a9b

Tags:

标签列表
最新留言