龙空技术网

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

Echa攻城狮 374

前言:

眼前看官们对“jqueryreadonly属性”大概比较关心,兄弟们都需要分析一些“jqueryreadonly属性”的相关知识。那么小编同时在网上收集了一些有关“jqueryreadonly属性””的相关内容,希望我们能喜欢,各位老铁们一起来了解一下吧!

作者:叫我詹躲躲

转发链接:

目录

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

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

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

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

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

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

236.扁平化数组方案一:递归 + ...

function flatten(arr, depth = -1) {  if (depth === -1) {    return [].concat(      ...arr.map((v) => (Array.isArray(v) ? this.flatten(v) : v))    );  }  if (depth === 1) {    return arr.reduce((a, v) => a.concat(v), []);  }  return arr.reduce(    (a, v) => a.concat(Array.isArray(v) ? this.flatten(v, depth - 1) : v),    []  );}flatten([1,[2,[3]]])复制代码
方案二:es6 原生 flat
function flatten(arr, depth = Infinity) {  return arr.flat(depth)}flatten([1,[2,[3]]])复制代码
对比两个数组并且返回其中不同的元素方案一:filter + includes

他原文有问题,以下方法的 4,5 没有返回

function diffrence(arrA, arrB) {  return arrA.filter((v) => !arrB.includes(v));}diffrence([1,2,3], [3,4,5,2])复制代码

需要再操作一遍

function diffrence(arrA, arrB) {  return arrA.filter((v) => !arrB.includes(v))    .concat(arrB.filter((v) => !arrA.includes(v)));}diffrence([1,2,3], [3,4,5,2])复制代码
方案二:hash + 遍历

算是方案1的变种吧,优化了 includes 的性能。

237.返回两个数组中相同的元素方案一:filter + includes

function intersection(arr1, arr2) {  return arr2.filter((v) => arr1.includes(v));}intersection([1,2,3], [3,4,5,2])复制代码
方案二:同理变种用 hash
function intersection(arr1, arr2) {    var set = new Set(arr2)  return arr1.filter((v) => set.has(v));}intersection([1,2,3], [3,4,5,2])复制代码
238.从右删除 n 个元素方案一:slice
function dropRight(arr, n = 0) {  return n < arr.length ? arr.slice(0, arr.length - n) : [];}dropRight([1,2,3,4,5], 2)复制代码
方案二: splice
function dropRight(arr, n = 0) {  return arr.splice(0, arr.length - n)}dropRight([1,2,3,4,5], 2)复制代码
方案三: slice 另一种
function dropRight(arr, n = 0) {  return arr.slice(0, -n)}dropRight([1,2,3,4,5], 2)复制代码
方案四: 修改 length
function dropRight(arr, n = 0) {    arr.length = Math.max(arr.length - n, 0)    return arr}dropRight([1,2,3,4,5], 2)复制代码
239.截取第一个符合条件的元素及其以后的元素方案一:slice + 循环
function dropElements(arr, fn) {  while (arr.length && !fn(arr[0])) arr = arr.slice(1);  return arr;}dropElements([1,2,3,4,5,1,2,3], (v) => v == 2)复制代码
方案二:findIndex + slice
function dropElements(arr, fn) {  return arr.slice(Math.max(arr.findIndex(fn), 0));}dropElements([1,2,3,4,5,1,2,3], (v) => v === 3)复制代码
方案三:splice + 循环
function dropElements(arr, fn) {  while (arr.length && !fn(arr[0])) arr.splice(0,1);  return arr;}dropElements([1,2,3,4,5,1,2,3], (v) => v == 2)复制代码
240.返回数组中下标间隔 nth 的元素方案一:filter
function everyNth(arr, nth) {  return arr.filter((v, i) => i % nth === nth - 1);}everyNth([1,2,3,4,5,6,7,8], 2)复制代码
方案二:方案一修改判断条件
function everyNth(arr, nth) {  return arr.filter((v, i) => (i+1) % nth === 0);}everyNth([1,2,3,4,5,6,7,8], 2)复制代码
241.返回数组中第 n 个元素(支持负数)方案一:slice
function nthElement(arr, n = 0) {  return (n >= 0 ? arr.slice(n, n + 1) : arr.slice(n))[0];}nthElement([1,2,3,4,5], 0)nthElement([1,2,3,4,5], -1)复制代码
方案二:三目运算符
function nthElement(arr, n = 0) {  return (n >= 0 ? arr[0] : arr[arr.length + n])}nthElement([1,2,3,4,5], 0)nthElement([1,2,3,4,5], -1)复制代码
242.返回数组头元素方案一:
function head(arr) {  return arr[0];}head([1,2,3,4])复制代码
方案二:
function head(arr) {  return arr.slice(0,1)[0];}head([1,2,3,4])复制代码
243.返回数组末尾元素方案一:
function last(arr) {  return arr[arr.length - 1];}复制代码
方案二:
function last(arr) {  return arr.slice(-1)[0];}last([1,2,3,4,5])复制代码
245.数组乱排方案一:洗牌算法
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;}shuffle([1,2,3,4,5])复制代码
方案二:sort + random
function shuffle(arr) {  return arr.sort((n,m)=>Math.random() - .5)}shuffle([1,2,3,4,5])复制代码
246.伪数组转换为数组方案一:Array.from
Array.from({length: 2})复制代码
方案二:prototype.slice
Array.prototype.slice.call({length: 2,1:1})复制代码
方案三:prototype.splice
Array.prototype.splice.call({length: 2,1:1},0)复制代码
浏览器对象 BOM195.判读浏览器是否支持 CSS 属性
/** * 告知浏览器支持的指定css属性情况 * @param {String} key - css属性,是属性的名字,不需要加前缀 * @returns {String} - 支持的属性情况 */function validateCssKey(key) {  const jsKey = toCamelCase(key); // 有些css属性是连字符号形成  if (jsKey in document.documentElement.style) {    return key;  }  let validKey = "";  // 属性名为前缀在js中的形式,属性值是前缀在css中的形式  // 经尝试,Webkit 也可是首字母小写 webkit  const prefixMap = {    Webkit: "-webkit-",    Moz: "-moz-",    ms: "-ms-",    O: "-o-",  };  for (const jsPrefix in prefixMap) {    const styleKey = toCamelCase(`${jsPrefix}-${jsKey}`);    if (styleKey in document.documentElement.style) {      validKey = prefixMap[jsPrefix] + key;      break;    }  }  return validKey;}/** * 把有连字符号的字符串转化为驼峰命名法的字符串 */function toCamelCase(value) {  return value.replace(/-(\w)/g, (matched, letter) => {    return letter.toUpperCase();  });}/** * 检查浏览器是否支持某个css属性值(es6版) * @param {String} key - 检查的属性值所属的css属性名 * @param {String} value - 要检查的css属性值(不要带前缀) * @returns {String} - 返回浏览器支持的属性值 */function valiateCssValue(key, value) {  const prefix = ["-o-", "-ms-", "-moz-", "-webkit-", ""];  const prefixValue = prefix.map((item) => {    return item + value;  });  const element = document.createElement("div");  const eleStyle = element.style;  // 应用每个前缀的情况,且最后也要应用上没有前缀的情况,看最后浏览器起效的何种情况  // 这就是最好在prefix里的最后一个元素是''  prefixValue.forEach((item) => {    eleStyle[key] = item;  });  return eleStyle[key];}/** * 检查浏览器是否支持某个css属性值 * @param {String} key - 检查的属性值所属的css属性名 * @param {String} value - 要检查的css属性值(不要带前缀) * @returns {String} - 返回浏览器支持的属性值 */function valiateCssValue(key, value) {  var prefix = ["-o-", "-ms-", "-moz-", "-webkit-", ""];  var prefixValue = [];  for (var i = 0; i < prefix.length; i++) {    prefixValue.push(prefix[i] + value);  }  var element = document.createElement("div");  var eleStyle = element.style;  for (var j = 0; j < prefixValue.length; j++) {    eleStyle[key] = prefixValue[j];  }  return eleStyle[key];}function validCss(key, value) {  const validCss = validateCssKey(key);  if (validCss) {    return validCss;  }  return valiateCssValue(key, value);}复制代码

segmentfault.com/a/11... 它里面有 forEach。

247.返回当前网页地址方案一:location

function currentURL() {  return window.location.href;}currentURL()复制代码
方案二:a 标签
function currentURL() {  var el = document.createElement('a')  el.href = ''  return el.href}currentURL()复制代码
获取滚动条位置
function getScrollPosition(el = window) {  return {    x: el.pageXOffset !== undefined ? el.pageXOffset : el.scrollLeft,    y: el.pageYOffset !== undefined ? el.pageYOffset : el.scrollTop,  };}复制代码
248.获取 url 中的参数方案一:正则 + reduce
function getURLParameters(url) {  return url    .match(/([^?=&]+)(=([^&]*))/g)    .reduce(      (a, v) => (        (a[v.slice(0, v.indexOf("="))] = v.slice(v.indexOf("=") + 1)), a      ),      {}    );}getURLParameters(location.href)复制代码
方案二:split + reduce
function getURLParameters(url) {  return url    .split('?') //取?分割    .slice(1) //不要第一部分    .join() //拼接    .split('&')//&分割    .map(v=>v.split('=')) //=分割    .reduce((s,n)=>{s[n[0]] = n[1];return s},{})}getURLParameters(location.href)// getURLParameters('')复制代码
方案三: URLSearchParams249.页面跳转,是否记录在 history 中方案一:
function redirect(url, asLink = true) {  asLink ? (window.location.href = url) : window.location.replace(url);}复制代码
方案二:
function redirect(url, asLink = true) {  asLink ? window.location.assign(url) : window.location.replace(url);}复制代码
250.滚动条回到顶部动画方案一: c - c / 8

c 没有定义

function scrollToTop() {  const scrollTop =    document.documentElement.scrollTop || document.body.scrollTop;  if (scrollTop > 0) {    window.requestAnimationFrame(scrollToTop);    window.scrollTo(0, c - c / 8);  } else {    window.cancelAnimationFrame(scrollToTop);  }}scrollToTop()复制代码

修正之后

function scrollToTop() {  const scrollTop =    document.documentElement.scrollTop || document.body.scrollTop;  if (scrollTop > 0) {    window.requestAnimationFrame(scrollToTop);    window.scrollTo(0, scrollTop - scrollTop / 8);  } else {    window.cancelAnimationFrame(scrollToTop);  }}scrollToTop()复制代码
251.复制文本方案一:
function copy(str) {  const el = document.createElement("textarea");  el.value = str;  el.setAttribute("readonly", "");  el.style.position = "absolute";  el.style.left = "-9999px";  el.style.top = "-9999px";  document.body.appendChild(el);  const selected =    document.getSelection().rangeCount > 0      ? document.getSelection().getRangeAt(0)      : false;  el.select();  document.execCommand("copy");  document.body.removeChild(el);  if (selected) {    document.getSelection().removeAllRanges();    document.getSelection().addRange(selected);  }}复制代码
方案二:cliboard.js252.检测设备类型方案一: ua
function detectDeviceType() {  return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(    navigator.userAgent  )    ? "Mobile"    : "Desktop";}detectDeviceType()复制代码
方案二:事件属性
function detectDeviceType() {  return ("ontouchstart" in window || navigator.msMaxTouchPoints)    ? "Mobile"    : "Desktop";}detectDeviceType()复制代码
253.Cookie增
function setCookie(key, value, expiredays) {  var exdate = new Date();  exdate.setDate(exdate.getDate() + expiredays);  document.cookie =    key +    "=" +    escape(value) +    (expiredays == null ? "" : ";expires=" + exdate.toGMTString());}复制代码
function delCookie(name) {  var exp = new Date();  exp.setTime(exp.getTime() - 1);  var cval = getCookie(name);  if (cval != null) {    document.cookie = name + "=" + cval + ";expires=" + exp.toGMTString();  }}复制代码
function getCookie(name) {  var arr,    reg = new RegExp("(^| )" + name + "=([^;]*)(;|$)");  if ((arr = document.cookie.match(reg))) {    return arr[2];  } else {    return null;  }}复制代码
清空

有时候我们想清空,但是又无法获取到所有的cookie。 这个时候我们可以了利用写满,然后再清空的办法。

日期 Date254.时间戳转换为时间默认为当前时间转换结果isMs 为时间戳是否为毫秒

function timestampToTime(timestamp = Date.parse(new Date()), isMs = true) {  const date = new Date(timestamp * (isMs ? 1 : 1000));  return `${date.getFullYear()}-${    date.getMonth() + 1 < 10 ? "0" + (date.getMonth() + 1) : date.getMonth() + 1  }-${date.getDate()} ${date.getHours()}:${date.getMinutes()}:${date.getSeconds()}`;}复制代码
补位可以改成 padStart补位还可以改成 slice

如果做海外的话,还会有时区问题,一般我用moment解决。如果想看原生的

获取当前时间戳

基于上一个想到的问题

方案一:Date.parse(new Date())方案二:Date.now()方案三:+new Date()文档对象 DOM255固定滚动条

/** * 功能描述:一些业务场景,如弹框出现时,需要禁止页面滚动,这是兼容安卓和 iOS 禁止页面滚动的解决方案 */let scrollTop = 0;function preventScroll() {  // 存储当前滚动位置  scrollTop = window.scrollY;  // 将可滚动区域固定定位,可滚动区域高度为 0 后就不能滚动了  document.body.style["overflow-y"] = "hidden";  document.body.style.position = "fixed";  document.body.style.width = "100%";  document.body.style.top = -scrollTop + "px";  // document.body.style['overscroll-behavior'] = 'none'}function recoverScroll() {  document.body.style["overflow-y"] = "auto";  document.body.style.position = "static";  // document.querySelector('body').style['overscroll-behavior'] = 'none'  window.scrollTo(0, scrollTop);}复制代码
256 判断当前位置是否为页面底部返回值为 true/false
function bottomVisible() {  return (    document.documentElement.clientHeight + window.scrollY >=    (document.documentElement.scrollHeight ||      document.documentElement.clientHeight)  );}复制代码
257判断元素是否在可视范围内partiallyVisible 为是否为完全可见
function elementIsVisibleInViewport(el, partiallyVisible = false) {  const { top, left, bottom, right } = el.getBoundingClientRect();  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;}复制代码
258.获取元素 css 样式
function getStyle(el, ruleName) {  return getComputedStyle(el, null).getPropertyValue(ruleName);}复制代码
259.进入全屏
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")); //某个元素进入全屏复制代码
260退出全屏
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();复制代码
261全屏事件
document.addEventListener("fullscreenchange", function (e) {  if (document.fullscreenElement) {    console.log("进入全屏");  } else {    console.log("退出全屏");  }});复制代码
数字 Number262.数字千分位分割
function commafy(num) {  return num.toString().indexOf(".") !== -1    ? num.toLocaleString()    : num.toString().replace(/(\d)(?=(?:\d{3})+$)/g, "$1,");}commafy(1000)复制代码
263.生成随机数
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)复制代码
264 时间戳转时间
/* 时间戳转时间 */function timestampToTime(cjsj) {	var date = new Date(cjsj); //时间戳为10位需*1000,时间戳为13位的话不需乘1000	var Y = date.getFullYear() + '-';	var M = (date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1) + '-';	var D = (date.getDate() + 1 < 10 ? '0' + (date.getDate()) : date.getDate()) + ' ';	return Y + M + D}复制代码
265 过滤富文本和空格为纯文本
/* 过滤富文本和空格为纯文本 */function filterHtml(str) {	return str.replace(/<[^<>]+>/g, '').replace(/ /ig, '');}复制代码
266 指定显示的文字数量多余的使用省略号代替
/*指定显示的文字数量多余的使用省略号代替*/function strEllp(str, num = str.length) {	var subStr = str.substring(0, num);	return subStr + (str.length > num ? '...' : '');}复制代码
267 获取滚动条当前的位置
// 获取滚动条当前的位置function getScrollTop() {	var scrollTop = 0	if (document.documentElement && document.documentElement.scrollTop) {		scrollTop = document.documentElement.scrollTop;	} else if (document.body) {		scrollTop = document.body.scrollTop;	}	return scrollTop}复制代码
268 获取当前可视范围的高度
// 获取当前可视范围的高度function getClientHeight() {	var clientHeight = 0	if (document.body.clientHeight && document.documentElement.clientHeight) {		clientHeight = Math.min(document.body.clientHeight, document.documentElement.clientHeight)	} else {		clientHeight = Math.max(document.body.clientHeight, document.documentElement.clientHeight)	}	return clientHeight}复制代码
269 获取文档完整的高度
// 获取文档完整的高度function getScrollHeight() {	return Math.max(document.body.scrollHeight, document.documentElement.scrollHeight)}复

本篇终于完结

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

《细品269个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 中的应用「前端篇」》

作者:叫我詹躲躲

转发链接:

标签: #jqueryreadonly属性 #jsforin退出 #jquery分页效果带省略号 #validcss #js随机数负数