编程技术文章分享与教程

网站首页 > 技术文章 正文

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

hmc789 2024-11-21 15:52:57 技术文章 2 ℃


作者:叫我詹躲躲

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

目录

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

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

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

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

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

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

203.原生js滑块验证

//event.clientX:鼠标点下的点到左侧x轴的距离
window.onload = function() {
    //事件处理  onmousedown  onmousemove  onmouseup
    var box = document.querySelector(".box")
    var btn = document.querySelector(".btn")
    var bg = document.querySelector(".bg")
    var text1 = document.querySelector(".text")
    //封装的选择器 声明式函数可以提升
    //			function fun(){
    //				
    //			}
    var flag = false; //标记
    btn.onmousedown = function(event) {
        var downx = event.clientX; //按下后获取的与x轴的距离
        btn.onmousemove = function(e) {
            var movex = e.clientX - downx; //滑块滑动的距离
            //移动的范围
            if (movex > 0) {
                this.style.left = movex + "px";
                bg.style.width = movex + "px";
                if (movex >= box.offsetWidth - 40) {
                    //验证成功
                    flag = true
                    text1.innerHTML = "验证成功"
                    text1.style.color = "#fff"
                    //清除事件
                    btn.onmousedown = null;
                    btn.onmousemove = null;
                }
            }
        }
    }
    //松开事件
    btn.onmouseup = function() {
        //清除事件
        btn.onmousemove = null;
        if (flag) return;
        this.style.left = 0;
        bg.style.width = 0 + "px";
    }
}
复制代码

204.纯 js无限加载瀑布

//随机[m,n]之间的整数 封装
function randomNumber(m, n) {
    return Math.floor(Math.random() * (n - m + 1) + m);
}
//随机颜色 封装
function randomColor() {
    return "rgb(" + randomNumber(0, 255) + "," + randomNumber(0, 255) + "," + randomNumber(0, 255) + ")";
}

//获取当前的scrollTop 
var scrollTopDistance;
//获取所有的ul 
var uls = document.querySelectorAll("ul");
var i = 0;
var k = i;

function waterFall() {
    for (i = k; i < k + 4; i++) {
        //创建li 
        var li = document.createElement("li");
        //随机颜色 
        li.style.backgroundColor = randomColor();
        //随机高度 
        li.style.height = randomNumber(120, 400) + "px";
        //手动转换为字符串 
        li.innerHTML = i + 1 + "";
        //插入到对应的ul中 
        //判断哪个ul的高度低,该次创建的li就插入到此ul中 
        var index = 0; //记录下标 
        for (var j = 0; j < uls.length; j++) {
            if (uls[j].offsetHeight < uls[index].offsetHeight) {
                index = j;
            }
        }
        //将元素节点插入文档中 
        uls[index].appendChild(li);
    }
    k = i;
    return uls[index].offsetHeight;
}
waterFall();
//鼠标滚轮事件,由于右侧没有滚轮,所以使用onmousewheel事件
window.onmousewheel = function() {
    //获取窗口的高度,要兼容浏览器
    var windowH = document.documentElement.clientHeight;
    //滚轮于top的距离,要兼容浏览器
    var scrollH = document.documentElement.scrollTop ||
        document.body.scrollTop;
    //获取窗口的可见高度
    var documentH = document.documentElement.scrollHeight ||
        document.body.scrollHeight;
    //窗口的高度 + 滚轮与顶部的距离 > 窗口的可见高度-200
    if (windowH + scrollH > documentH - 200) {
        //执行此函数 
        waterFall()
    }
}
复制代码

205.jQuery两个元素比较高度

$(*function* () {
  *var* w_max = 0;
  *//求最大高度*
  $("#MenuNavigation li").each(*function* () {
?    *var* w = $(*this*).innerWidth();
?    w_max = w > w_max ? w : w_max;
  })
  $("#MenuNavigation li").width(w_max)
  *//将最大高度赋值给所有元素,*
})
复制代码

206.js定时清除缓存,存储缓存,获取缓存

// 封装本地存储的方法
export const storage = {
  set: function(variable, value, ttl_ms) {
    var data = { value: value, expires_at: new Date(ttl_ms).getTime() };
    localStorage.setItem(variable.toString(), JSON.stringify(data));
  },
  get: function(variable) {
    var data = JSON.parse(localStorage.getItem(variable.toString()));
    if (data !== null) {
      debugger
      if (data.expires_at !== null && data.expires_at < new Date().getTime()) {
        localStorage.removeItem(variable.toString());
      } else {
        return data.value;
      }
    }
    return null;
  },
  remove(key) {
    localStorage.removeItem(key);
  }
}
复制代码

207.数组降维

//数组降维
reduceDimension(arr) {
      var reduced = [];
      for (var i = 0; i < arr.length; i++) {
        reduced = reduced.concat(arr[i]);
      }
      return reduced;
}
复制代码

208.设置cookie,获取cookie,删除cookie

 var cookieUtil = {
  getCookie: function (name) {
    var arrCookie = document.cookie.split("; ");
    for (var i = 0; i < arrCookie.length; i++) {
      var cookieItem = arrCookie[i].split('=');
      if (cookieItem[0] == name) {
        return cookieItem[1];
      }
    }
    return undefined;
  },
  setCookie: function (name, value, expires, path, domain, secure) {
    var cookieText = encodeURIComponent(name) + "=" +
      encodeURIComponent(value);
    if (expires instanceof Date) {
      cookieText += "; expires=" + expires.toGMTString();
    }
    if (path) {
      cookieText += "; path=" + path;
    }
    if (domain) {
      cookieText += "; domain=" + domain;
    }
    if (secure) {
      cookieText += "; secure";
    }
    document.cookie = cookieText;
  },
  removeCookie: function (name, path, domain, secure) {
    this.set(name, "", new Date(0), path, domain, secure);
  }
} 
复制代码

209.判读是否为外链

/**

 * @description 判读是否为外链
 * @param path
 * @returns {boolean}
   */
   export function isExternal(path) {
     return /^(https?:|mailto:|tel:)/.test(path);
   }

复制代码

210.校验密码是否小于6位

/**
    * @description 校验密码是否小于6位
    * @param str
    * @returns {boolean}
      */
      export function isPassword(str) {
        return str.length >= 6;
      }
      
复制代码

211.判断是否为数字

/**

  * @description 判断是否为数字
  * @param value
* @returns {boolean}
   */
   export function isNumber(value) {
     const reg = /^[0-9]*$/;
     return reg.test(value);
   }
复制代码

212.判断是否是名称

 /**

   * @description 判断是否是名称
   * @param value
 * @returns {boolean}
    */
    export function isName(value) {
      const reg = /^[\u4e00-\u9fa5a-zA-Z0-9]+$/;
      return reg.test(value);
    }
复制代码

213.判断是否为IP

/**

  * @description 判断是否为IP
  * @param ip
* @returns {boolean}
   */
   export function isIP(ip) {
     const reg = /^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$/;
     return reg.test(ip);
   }
复制代码

214.判断是否是传统网站

/**

  * @description 判断是否是传统网站
  * @param url
* @returns {boolean}
   */
   export function isUrl(url) {
     const reg = /^(https?|ftp):\/\/([a-zA-Z0-9.-]+(:[a-zA-Z0-9.&%$-]+)*@)*((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}|([a-zA-Z0-9-]+\.)*[a-zA-Z0-9-]+\.(com|edu|gov|int|mil|net|org|biz|arpa|info|name|pro|aero|coop|museum|[a-zA-Z]{2}))(:[0-9]+)*(\/($|[a-zA-Z0-9.,?'\\+&%$#=~_-]+))*$/;
     return reg.test(url);
   }
复制代码

215.判断是否是小写字母

/**

  * @description 判断是否是小写字母
  * @param str
* @returns {boolean}
   */
   export function isLowerCase(str) {
     const reg = /^[a-z]+$/;
     return reg.test(str);
   }
复制代码

216.判断是否是大写字母

/**

  * @description 判断是否是大写字母
  * @param str
* @returns {boolean}
   */
   export function isUpperCase(str) {
     const reg = /^[A-Z]+$/;
     return reg.test(str);
   }
复制代码

217.判断是否是大写字母开头

/**

  * @description 判断是否是大写字母开头
  * @param str
* @returns {boolean}
   */
   export function isAlphabets(str) {
     const reg = /^[A-Za-z]+$/;
     return reg.test(str);
   }
复制代码

218.判断是否是字符串

/**

  * @description 判断是否是字符串
* @param str
 * @returns {boolean}
   */
   export function isString(str) {
     return typeof str === "string" || str instanceof String;
   }
复制代码

219.判断是否是数组

/**

  * @description 判断是否是数组
    * @param arg
  * @returns {arg is any[]|boolean}
    */
  export function isArray(arg) {
     if (typeof Array.isArray === "undefined") {
   return Object.prototype.toString.call(arg) === "[object Array]";
     }
     return Array.isArray(arg);
   }
复制代码

220.判断是否是端口号

/**

  * @description 判断是否是端口号
  * @param str
* @returns {boolean}
   */
   export function isPort(str) {
     const reg = /^([0-9]|[1-9]\d|[1-9]\d{2}|[1-9]\d{3}|[1-5]\d{4}|6[0-4]\d{3}|65[0-4]\d{2}|655[0-2]\d|6553[0-5])$/;
     return reg.test(str);
   }
复制代码

221.判断是否是手机号

/**

  * @description 判断是否是手机号
  * @param str
* @returns {boolean}
   */
   export function isPhone(str) {
     const reg = /^1\d{10}$/;
     return reg.test(str);
   }
复制代码

222.判断是否是身份证号(第二代)

/**

  * @description 判断是否是身份证号(第二代)
  * @param str
* @returns {boolean}
   */
   export function isIdCard(str) {
     const reg = /^[1-9]\d{5}(18|19|([23]\d))\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/;
     return reg.test(str);
   }
复制代码

223.判断是否是邮箱

/**

  * @description 判断是否是邮箱
  * @param str
* @returns {boolean}
   */
   export function isEmail(str) {
     const reg = /^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/;
     return reg.test(str);
   }
复制代码

224.判断是否中文

/**

  * @description 判断是否中文
  * @param str
* @returns {boolean}
   */
   export function isChina(str) {
     const reg = /^[\u4E00-\u9FA5]{2,4}$/;
     return reg.test(str);
   }
复制代码

225.判断是否为空

/**

  * @description 判断是否为空
    * @param str
    * @returns {boolean}
      */
      export function isBlank(str) {
        return (
    str == null ||
  false ||
   str === "" ||
   str.trim() === "" ||
   str.toLocaleLowerCase().trim() === "null"
     );
   }
复制代码

226.判断是否为固话

/**

  * @description 判断是否为固话
  * @param str
* @returns {boolean}
   */
   export function isTel(str) {
     const reg = /^(400|800)([0-9\\-]{7,10})|(([0-9]{4}|[0-9]{3})(-| )?)?([0-9]{7,8})((-| |转)*([0-9]{1,4}))?$/;
     return reg.test(str);
   }
复制代码

227.判断是否为数字且最多两位小数

/**

  * @description 判断是否为数字且最多两位小数
  * @param str
* @returns {boolean}
   */
   export function isNum(str) {
     const reg = /^\d+(\.\d{1,2})?$/;
     return reg.test(str);
   }
复制代码

228.判断经度 -180.0~+180.0(整数部分为0~180,必须输入1到5位小数)

/**

  * @description 判断经度 -180.0~+180.0(整数部分为0~180,必须输入1到5位小数)
  * @param str
* @returns {boolean}
   */
   export function isLongitude(str) {
     const reg = /^[-|+]?(0?\d{1,2}\.\d{1,5}|1[0-7]?\d{1}\.\d{1,5}|180\.0{1,5})$/;
     return reg.test(str);
   }
复制代码

229.判断纬度 -90.0~+90.0(整数部分为0~90,必须输入1到5位小数)

/**

  * @description 判断纬度 -90.0~+90.0(整数部分为0~90,必须输入1到5位小数)
  * @param str
* @returns {boolean}
   */
   export function isLatitude(str) {
     const reg = /^[-|+]?([0-8]?\d{1}\.\d{1,5}|90\.0{1,5})$/;
     return reg.test(str);
   }
复制代码

230.rtsp校验只要有rtsp://

/**

  * @description rtsp校验,只要有rtsp://
  * @param str
  * @returns {boolean}
    */
  export function isRTSP(str) {
     const reg = /^rtsp:\/\/([a-z]{0,10}:.{0,10}@)?(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$/;
     const reg1 = /^rtsp:\/\/([a-z]{0,10}:.{0,10}@)?(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5]):[0-9]{1,5}/;
     const reg2 = /^rtsp:\/\/([a-z]{0,10}:.{0,10}@)?(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\//;
     return reg.test(str) || reg1.test(str) || reg2.test(str);
   }
复制代码

231.判断IE浏览器版本和检测是否为非IE浏览器

function IEVersion() {
	var userAgent = navigator.userAgent; //取得浏览器的userAgent字符串  
	var isIE = userAgent.indexOf("compatible") > -1 && userAgent.indexOf("MSIE") > -1; //判断是否IE<11浏览器  
	var isEdge = userAgent.indexOf("Edge") > -1 && !isIE; //判断是否IE的Edge浏览器  
	var isIE11 = userAgent.indexOf('Trident') > -1 && userAgent.indexOf("rv:11.0") > -1;
	if (isIE) {
		var reIE = new RegExp("MSIE (\\d+\\.\\d+);");
		reIE.test(userAgent);
		var fIEVersion = parseFloat(RegExp["$1"]);
		if (fIEVersion == 7) {
			return 7;
		} else if (fIEVersion == 8) {
			return 8;
		} else if (fIEVersion == 9) {
			return 9;
		} else if (fIEVersion == 10) {
			return 10;
		} else {
			return 6; //IE版本<=7
		}
	} else if (isEdge) {
		return 'edge'; //edge
	} else if (isIE11) {
		return 11; //IE11  
	} else {
		return -1; //不是ie浏览器
	}
}
复制代码

232.数组去重

方案一:Set + ...

function noRepeat(arr) {
  return [...new Set(arr)];
}
noRepeat([1,2,3,1,2,3])
复制代码

方案二:Set + Array.from

function noRepeat(arr) {
  return Array.from(new Set(arr));
}
noRepeat([1,2,3,1,2,3])
复制代码

方案三:双重遍历比对下标

function noRepeat(arr) {
  return arr.filter((v, idx)=>idx == arr.lastIndexOf(v))
}
noRepeat([1,2,3,1,2,3])
复制代码

方案四:单遍历 + Object 特性

Object 的特性是 Key 不会重复。 这里使用 values 是因为可以保留类型,keys 会变成字符串。

function noRepeat(arr) {
  return Object.values(arr.reduce((s,n)=>{
    s[n] = n;
    return s
  },{}))
}
noRepeat([1,2,3,1,2,3])
复制代码

后记

针对于上述的方案,还有其他变种实现。

233.查找数组最大

方案一:Math.max + ...

function arrayMax(arr) {
  return Math.max(...arr);
}
arrayMax([-1,-4,5,2,0])
复制代码

方案二:Math.max + apply

function arrayMax(arr) {
  return Math.max.apply(Math, arr)
}
arrayMax([-1,-4,5,2,0])
复制代码

方案三:Math.max + 遍历

function arrayMax(arr) {
  return arr.reduce((s,n)=>Math.max(s, n))
}
arrayMax([-1,-4,5,2,0])
复制代码

方案四:比较、条件运算法 + 遍历

function arrayMax(arr) {
  return arr.reduce((s,n)=>s>n?s:n)
}
arrayMax([-1,-4,5,2,0])
复制代码

方案五:排序

function arrayMax(arr) {
  return arr.sort((n,m)=>m-n)[0]
}
arrayMax([-1,-4,5,2,0])
复制代码

234.查找数组最小

同上,不明白为什么要分成两个题目。

  1. Math.max 换成 Math.min
  2. s>n?s:n 换成 `s
  3. (n,m)=>m-n 换成 (n,m)=>n-m,或者直接取最后一个元素

235.返回已 size 为长度的数组分割的原数组

方案一:Array.from + slice

function chunk(arr, size = 1) {
  return Array.from(
    {
      length: Math.ceil(arr.length / size),
    },
    (v, i) => arr.slice(i * size, i * size + size)
  );
}
chunk([1,2,3,4,5,6,7,8],3)
复制代码

方案二:Array.from + splice

function chunk(arr, size = 1) {
  return Array.from(
    {
      length: Math.ceil(arr.length / size),
    },
    (v, i) => arr.splice(0, size)
  );
}
chunk([1,2,3,4,5,6,7,8],3)
复制代码

方案三:遍历 + splice

function chunk(arr, size = 1) {
    var _returnArr = [];
    while(arr.length){
        _returnArr.push(arr.splice(0, size))
    }
    return _returnArr
}
chunk([1,2,3,4,5,6,7,8],3)
复制代码

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

方案一:reduce

function countOccurrences(arr, value) {
  return arr.reduce((a, v) => (v === value ? a + 1 : a + 0), 0);
}
countOccurrences([1,2,3,4,5,1,2,1,2,3], 1)
复制代码

方案二:filter

function countOccurrences(arr, value) {
  return arr.filter(v=>v===value).length
}
countOccurrences([1,2,3,4,5,1,2,1,2,3], 1)
复制代码

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

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

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

细品269个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

标签列表
最新留言