

你可能不知道的 64 个非常实用的 JS 小技巧
source link: https://www.tuicool.com/articles/3AfMve2
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

前言
何为技巧,意指表现在文学、工艺、体育等方面的巧妙技能。代码作为一门现代高级工艺,推动着人类科学技术的发展,同时犹如文字一样承托着人类文化的进步。
每写好一篇文章,都会使用大量的写作技巧。 烘托、渲染、悬念、铺垫、照应、伏笔、联想、想象、抑扬结合、点面结合、动静结合、叙议结合、情景交融、首尾呼应、衬托对比、白描细描、比喻象征、借古讽今、卒章显志、承上启下、开门见山、动静相衬、虚实相生、实写虚写、托物寓意、咏物抒情
等,这些应该都是我们从小到大写文章而接触到的写作技巧。
作为程序猿的我们,写代码同样也需要大量的写作技巧。一份良好的代码能让人耳目一新,让人容易理解,让人舒服自然,同时也让自己成就感满满(哈哈,这个才是重点)。因此,我整理下三年来自己使用到的一些 JavaScript开发技巧 ,希望能让你写出耳目一新、容易理解、舒服自然的代码。
以下演示全是ES6版本的书写,在 Webpack
和 Babel
的加持下就不能好好写ES6吗,还写什么ES3和ES5呢,更别管那弱智的IE浏览器了,IE浏览器都快被淘汰了, Microsoft
都宣布放弃使用自研的浏览器内核而使用 Google
开源的 Chromium
内核了。
目录
既然写文章有这么多的写作技巧,那么我也需要对 JavaScript开发技巧 整理一下,起个易记的名字。
√ String Skill : 字符串技巧
√ Number Skill : 数值技巧
√ Boolean Skill : 布尔值技巧
√ Array Skill : 数组技巧
√ Object Skill : 对象技巧
√ Function Skill : 函数技巧
√ DOM Skill : DOM技巧
备注
-
代码只作演示用途,不会详细说明ES6语法
-
如有不明白的语法问题请参考阮一峰老师的《ECMAScript 6 入门》
-
《ECMAScript 6 入门》一直保持更新,建议收藏,平时查看
String Skill
时间对比: 时间个位数形式需补0
1const time1 = "2019-03-31 21:00:00"; 2const time2 = "2019-05-01 09:00:00"; 3const overtime = time1 > time2; 4// overtime => false
格式化金钱
1const ThousandNum = num => num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ","); 2const money = ThousandNum(19941112); 3// money => "19,941,112"
生成随机ID
1const RandomId = len => Math.random().toString(36).substr(3, len); 2const id = RandomId(10); 3// id => "jg7zpgiqva"
生成随机HEX色值
1const RandomColor = () => "#" + Math.floor(Math.random() * 0xffffff).toString(16).padEnd(6, "0"); 2const color = RandomColor(); 3// color => "#f03665"
生成星级评分
1const StartScore = rate => "★★★★★☆☆☆☆☆".slice(5 - rate, 10 - rate); 2const start = StartScore(3); 3// start => "★★★"
操作URL查询参数
1const params = new URLSearchParams(location.search.replace(/\?/ig, "")); // location.search = "?name=yajun&sex=female" 2params.has("yajun"); // true 3params.get("sex"); // "female"
Number Skill
取整:
代替正数的 Math.floor()
,代替负数的 Math.ceil()
1const num1 = ~~ 1.69; 2const num2 = 1.69 | 0; 3const num3 = 1.69 >> 0; 4// num1 num2 num3 => 1 1 1
补零
1const FillZero = (num, len) => num.toString().padStart(len, "0"); 2const num = FillZero(169, 5); 3// num => "00169"
转数值:
只对 null、""、false、数值字符串
有效
1const num1 = +null; 2const num2 = +""; 3const num3 = +false; 4const num4 = +"169"; 5// num1 num2 num3 num4 => 0 0 0 169
时间戳
1const timestamp = +new Date("2019-03-31"); 2// timestamp => 1553990400000
精确小数
1const RoundNum = (num, decimal) => Math.round(num * 10 ** decimal) / 10 ** decimal; 2const num = RoundNum(1.69, 1); 3// num => 1.7
判断奇偶
1const OddEven = num => !!(num & 1) ? "odd" : "even"; 2const num = OddEven(2); 3// num => "even"
取最小最大值
1const arr = [0, 1, 2]; 2const min = Math.min(...arr); 3const max = Math.max(...arr); 4// min max => 0 2
生成范围随机数
1const RandomNum = (min, max) => Math.floor(Math.random() * (max - min + 1)) + min; 2const num = RandomNum(1, 10);
Boolean Skill
短路运算符
1const a = d && 1; // 满足条件赋值:取假运算,从左到右依次判断,遇到假值返回假值,后面不再执行,否则返回最后一个真值 2const b = d || 1; // 默认赋值:取真运算,从左到右依次判断,遇到真值返回真值,后面不再执行,否则返回最后一个假值 3const c = !d; // 取假赋值:单个表达式转换为true则返回false,否则返回true
判断数据类型: undefined、null、string、number、boolean、array、object、symbol、date、regexp、function、asyncfunction、arguments、set、map、weakset、weakmap
1function DataType(tgt, type) { 2 const dataType = Object.prototype.toString.call(tgt).replace(/\[object /g, "").replace(/\]/g, "").toLowerCase(); 3 return type ? dataType === type : dataType; 4} 5DataType("yajun"); // "string" 6DataType(19941112); // "number" 7DataType(true); // "boolean" 8DataType([], "array"); // true 9DataType({}, "array"); // false
是否为空数组
1const arr = []; 2const flag = Array.isArray(arr) && !arr.length; 3// flag => true
是否为空对象
1const obj = {}; 2const flag = DataType(obj, "object") && !Object.keys(obj).length; 3// flag => true
满足条件时执行
1const flagA = true; // 条件A 2const flagB = false; // 条件B 3(flagA || flagB) && Func(); // 满足A或B时执行 4(flagA || !flagB) && Func(); // 满足A或不满足B时执行 5flagA && flagB && Func(); // 同时满足A和B时执行 6flagA && !flagB && Func(); // 满足A且不满足B时执行
为非假值时执行
1const flag = false; // undefined、null、""、0、false、NaN 2!flag && Func();
数组不为空时执行
1const arr = [0, 1, 2]; 2arr.length && Func();
对象不为空时执行
1const obj = { a: 0, b: 1, c: 2 }; 2Object.keys(obj).length && Func();
函数退出代替条件分支退出
1if (flag) { 2 Func(); 3 return false; 4} 5// 换成 6if (flag) { 7 return Func(); 8}
switch/case使用区间
1const age = 26; 2switch (true) { 3 case isNaN(age): 4 console.log("not a number"); 5 break; 6 case (age < 18): 7 console.log("under age"); 8 break; 9 case (age >= 18): 10 console.log("adult"); 11 break; 12 default: 13 console.log("please set your age"); 14 break; 15}
Array Skill
克隆数组
1const _arr = [0, 1, 2]; 2const arr = [..._arr]; 3// arr => [0, 1, 2]
合并数组
1const arr1 = [0, 1, 2]; 2const arr2 = [3, 4, 5]; 3const arr = [...arr1, ...arr2]; 4// arr => [0, 1, 2, 3, 4, 5];
去重数组
1const arr = [...new Set([0, 1, 1, null, null])]; 2// arr => [0, 1, null]
混淆数组
1const arr = [0, 1, 2, 3, 4, 5].slice().sort(() => Math.random() - .5); 2// arr => [3, 4, 0, 5, 1, 2]
清空数组
1const arr = [0, 1, 2]; 2arr.length = 0; 3// arr => []
截断数组
1const arr = [0, 1, 2]; 2arr.length = 2; 3// arr => [0, 1]
交换赋值
1let a = 0; 2let b = 1; 3[a, b] = [b, a]; 4// a b => 1 0
过滤空值: undefined、null、""、0、false、NaN
1const arr = [undefined, null, "", 0, false, NaN, 1, 2].filter(Boolean); 2// arr => [1, 2]
异步累计
1async function Func(deps) { 2 return deps.reduce(async(t, v) => { 3 const dep = await t; 4 const version = await Todo(v); 5 dep[v] = version; 6 return dep; 7 }, Promise.resolve({})); 8} 9const result = await Func(); // 需在async包围下使用
数组首部插入成员
1let arr = [1, 2]; // 以下方法任选一种 2arr.unshift(0); 3arr = [0].concat(arr); 4arr = [0, ...arr]; 5// arr => [0, 1, 2]
数组尾部插入成员
1let arr = [0, 1]; // 以下方法任选一种 2arr.push(2); 3arr.concat(2); 4arr[arr.length] = 2; 5arr = [...arr, 2]; 6// arr => [0, 1, 2]
统计数组成员个数
1const arr = [0, 1, 1, 2, 2, 2]; 2const count = arr.reduce((t, c) => { 3 t[c] = t[c] ? ++ t[c] : 1; 4 return t; 5}, {}); 6// count => { 0: 1, 1: 2, 2: 3 }
解构数组成员嵌套
1const arr = [0, 1, [2, 3, [4, 5]]]; 2const [a, b, [c, d, [e, f]]] = arr; 3// a b c d e f => 0 1 2 3 4 5
解构数组成员别名
1const arr = [0, 1, 2]; 2const { 0: a, 1: b, 2: c } = arr; 3// a b c => 0 1 2
解构数组成员默认值
1const arr = [0, 1, 2]; 2const [a, b, c = 3, d = 4] = arr; 3// a b c d => 0 1 2 4
获取随机数组成员
1const arr = [0, 1, 2, 3, 4, 5]; 2const randomItem = arr[Math.floor(Math.random() * arr.length)]; 3// randomItem => 1
创建指定长度数组
1const arr = [...new Array(3).keys()]; 2// arr => [0, 1, 2]
创建指定长度且值相等的数组
1const arr = new Array(3).fill(0); 2// arr => [0, 0, 0]
reduce代替map和filter
1const _arr = [0, 1, 2]; 2 3// map 4const arr = _arr.map(v => v * 2); 5const arr = _arr.reduce((t, c) => { 6 t.push(c * 2); 7 return t; 8}, []); 9// arr => [0, 2, 4] 10 11// filter 12const arr = _arr.filter(v => v > 0); 13const arr = _arr.reduce((t, c) => { 14 c > 0 && t.push(c); 15 return t; 16}, []); 17// arr => [1, 2] 18 19// map和filter 20const arr = _arr.map(v => v * 2).filter(v => v > 2); 21const arr = _arr.reduce((t, c) => { 22 c = c * 2; 23 c > 2 && t.push(c); 24 return t; 25}, []); 26// arr => [4]
Object Skill
克隆对象
1const _obj = { a: 0, b: 1, c: 2 }; // 以下方法任选一种 2const obj = { ..._obj }; 3const obj = JSON.parse(JSON.stringify(_obj)); 4// obj => { a: 0, b: 1, c: 2 }
合并对象
1const obj1 = { a: 0, b: 1, c: 2 }; 2const obj2 = { c: 3, d: 4, e: 5 }; 3const obj = { ...obj1, ...obj2 }; 4// obj => { a: 0, b: 1, c: 3, d: 4, e: 5 }
对象字面量: 获取环境变量时必用此方法,用它一直爽,一直用它一直爽
1const env = "prod"; 2const link = { 3 dev: "Development Address", 4 test: "Testing Address", 5 prod: "Production Address" 6}[env]; 7// link => "Production Address"
对象变量属性
1const flag = false; 2const obj = { 3 a: 0, 4 b: 1, 5 [flag ? "c" : "d"]: 2 6}; 7// obj => { a: 0, b: 1, d: 2 }
创建纯空对象
1const obj = Object.create(null); 2Object.prototype.a = 0; 3// obj => {}
删除对象无用属性
1const obj = { a: 0, b: 1, c: 2 }; // 只想拿b和c 2const { a, ...rest } = obj; 3// rest => { b: 1, c: 2 }
解构对象属性嵌套
1const obj = { a: 0, b: 1, c: { d: 2, e: 3 } }; 2const { c: { d, e } } = obj; 3// d e => 2 3
解构对象属性别名
1const obj = { a: 0, b: 1, c: 2 }; 2const { a, b: d, c: e } = obj; 3// a d e => 0 1 2
解构对象属性默认值
1const obj = { a: 0, b: 1, c: 2 }; 2const { a, b = 2, d = 3 } = obj; 3// a b d => 0 1 3
Function Skill
函数自执行
1const Func = function() {}(); // 常用 2 3(function() {})(); // 常用 4(function() {}()); // 常用 5[function() {}()]; 6 7+ function() {}(); 8- function() {}(); 9~ function() {}(); 10! function() {}(); 11 12new function() {}; 13new function() {}(); 14void function() {}(); 15typeof function() {}(); 16delete function() {}(); 17 181, function() {}(); 191 ^ function() {}(); 201 > function() {}();
隐式返回值:
只能用于 单语句返回值箭头函数
,如果返回值是对象必须使用 ()
包住
1const Func = function(name) { 2 return "I Love " + name; 3}; 4// 换成 5const Func = name => "I Love " + name;
一次性函数: 适用于运行一些只需执行一次的初始化代码
1function Func() { 2 console.log("x"); 3 Func = function() { 4 console.log("y"); 5 } 6}
惰性载入函数: 函数内判断分支较多较复杂时可大大节约资源开销
1function Func() { 2 if (a === b) { 3 console.log("x"); 4 } else { 5 console.log("y"); 6 } 7} 8// 换成 9function Func() { 10 if (a === b) { 11 Func = function() { 12 console.log("x"); 13 } 14 } else { 15 Func = function() { 16 console.log("y"); 17 } 18 } 19 return Func(); 20}
检测非空参数
1function IsRequired() { 2 throw new Error("param is required"); 3} 4function Func(name = IsRequired()) { 5 console.log("I Love " + name); 6} 7Func(); // "param is required" 8Func("雅君妹纸"); // "I Love 雅君妹纸"
字符串创建函数
1const Func = new Function("name", "console.log(\"I Love \" + name)");
优雅处理错误信息
1try { 2 Func(); 3} catch (e) { 4 location.href = "https://stackoverflow.com/search?q=[js]+" + e.message; 5}
优雅处理Async/Await参数
1function AsyncTo(promise) { 2 return promise.then(data => [null, data]).catch(err => [err]); 3} 4const [err, res] = await AsyncTo(Func());
优雅处理多个函数返回值
1function Func() { 2 return Promise.all([ 3 fetch("/user"), 4 fetch("/comment") 5 ]); 6} 7const [user, comment] = await Func(); // 需在async包围下使用
DOM Skill
显示全部DOM边框: 调试页面元素边界时使用
1[].forEach.call($$("*"), dom => { 2 dom.style.outline = "1px solid #" + (~~(Math.random() * (1 << 24))).toString(16); 3});
自适应页面:
页面基于一张设计图但需做多款机型自适应,元素尺寸使用 rem
进行设置
1function AutoResponse(width = 750) { 2 const target = document.documentElement; 3 target.clientWidth >= 600 4 ? (target.style.fontSize = "80px") 5 : (target.style.fontSize = target.clientWidth / width * 100 + "px"); 6}
过滤XSS
1function FilterXss(content) { 2 let elem = document.createElement("div"); 3 elem.innerText = content; 4 const result = elem.innerHTML; 5 elem = null; 6 return result; 7}
存取LocalStorage: 反序列化取,序列化存
1const love = JSON.parse(localStorage.getItem("love")); 2localStorage.setItem("love", JSON.stringify("I Love 雅君妹纸"));
结语
写到最后总结得差不多了,后续如果我想起还有哪些 JavaScript开发技巧 遗漏的,会继续在这篇文章上补全,同时也希望各位倔友对文章里的要点进行补充或者提出自己的见解。欢迎在下方进行评论或补充喔,喜欢的 点个赞 或 收个藏 ,保证你在开发时用得上。
:heart: 看完三件事
如果你觉得这篇内容对你挺有启发,我想邀请你帮我三个小忙:
-
点个「 在看 」,让更多的人也能看到这篇内容(喜欢不点在看,都是耍流氓 -_-)
-
关注我的博客 https://github.com/SHERlocked93/blog ,让我们成为长期关系
-
关注公众号「 前端下午茶 」,持续为你推送精选好文,也可以加我为好友,随时聊骚。
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK