“阅前必阅”
JavaScript博大精深,本人只是在工作中,发现了一些js的各种写法,下面介绍的是一些能简化代码量的写法,但是有一些我是不太推荐的,详细原因也有论述。抛的砖是砸到头了还是引出了玉,就看各位了。
切换变量0和1
1 2 3 4 5 6 7 8 9 10 11
| // if判断可以这么写 let flag = 0; if (flag === 0) { flag = 1; } else { flag = 0; } // 也可以用三目运算符 flag = flag === 0 ? 1 : 0; // 也可以使用位异或(^) flag ^= 1;
|
一般我要求自己的团队在js上是尽量少用位运算,为什么呢?因为位运算其实二进制数执行运算,包括与&、或|、异或^、非~、左移<<、右移>>都是整数的逐位运算。然而,不幸的是在js内部所有数字都是双精度浮点数,所以这些运算js会先转为整数再运算,而且代码阅读性也会降低。
其实说到位运算,还不得不提一个月更贴,为什么
1
| console.log(0.1 + 0.2 === 0.3); // false
|
总结一句就是十进制转二进制的精度丢失,如果想深入了解,推荐一篇文章0.1 + 0.2不等于0.3?为什么JavaScript有这种“骚”操作?
!!
继续说位运算的非,我在项目中看到越来越多的人用!!来判空等操作,本身来讲也没问题,但是毫无节制的使用!!真的有必要吗?比如已知表达式就是一个Boolean值,还需要这样判断吗?
还是先讲讲!!的逻辑吧,非运算字面比较简单——真就是假,假就是真,不过js的类型特点,还是详细看下:
1 2 3 4 5 6 7 8 9
| console.log(!null); // true let u = void 0; // undefined console.log(!u); // true console.log(!0); // true console.log(!1); // false console.log(!''); // true console.log(!'a'); // false console.log(!{}); // false console.log(!{ a: 'a' }); // false
|
这里基本涵盖了所有类型(boolean就没必要参与了),可以看到null、undefined、0、’’是true,其它为false,所以我们就明白为什么很多人用这个来判断空字符串了吧,问题却来了0不是空啊,比如常见场景我们Http请求时,要剔除空参数,但如果参数有个0,那就尴尬了吧~即使你真的要将0纳入false范畴,我也更推荐下面的做法:
1 2 3 4 5 6 7 8 9
| console.log(Boolean('null')); let u = void 0; // undefined console.log(Boolean(u)); console.log(Boolean(0)); console.log(Boolean(1)); console.log(Boolean('')); console.log(Boolean('a')); console.log(Boolean({})); console.log(Boolean({ a: 'a' }));
|
如果你只是单纯的想判断空,可以使用下面的方法
1 2 3 4 5 6
| function isEmpty(str) { return null == str || '' == str; } console.log(isEmpty(0)); console.log(isEmpty(void 0)); console.log(isEmpty(null));
|
交换值
如果用位运算,则
1 2 3 4 5 6 7
| let a = 1; let b = 2; a ^= b; b ^= a; a ^= b; console.log(a); // 2 console.log(b); // 1
|
但与借助中间值,似乎差距不大
1 2 3 4 5 6 7
| let a = 1; let b = 2; let c = a; a = b; b = c; console.log(a); // 2 console.log(b); // 1
|
而现在基本都支持ES6的情况下,其实可以用解构才操作
1 2 3 4 5
| let a = 1; let b = 2; [a, b] = [b, a]; console.log(a); // 2 console.log(b); // 1
|
1 2 3 4 5 6 7 8 9
| // 从对象中取值 let obj = { a: 1, b: 2, c: 3 }; let { a, b, c } = obj; console.log(a, b, c); // 1,2,3
// 从数组中取值 let arr = [1, 2, 3, 4, 5]; let [a, , , b, , c] = arr; console.log(a, b, c); // 1 4 undefined
|
但解构的作用可不仅仅是如此,还有很多妙处,比如:从数组中取一个值,如果该索引不存在则赋一个默认值
1 2 3 4 5 6 7
| let arr = [1]; let value = 'a'; if (arr.length > 1) { value = arr[1]; } console.log(value); // a
|
而用解构,则仅需
1 2 3
| let arr = [1]; let [, value = 'a'] = arr; console.log(value); // a
|
用户签到
在开发中,我用位运算较多的一个场景——签到,比如下面的做法来实现判断用户一个月的签到情况:
- 每天对应一个数
1
| dayNum = Math.pow(2, day); // day是日期(几号)
|
- 如果该天签到,则签到数值加上该数值
- 判断某天是否签到
1
| (dayNum & daySum) === dayNum
|
比如
1 2 3 4 5 6 7 8
| // 假设用户1 3 5号三天签到了 let daySum = Math.pow(2, 1) + Math.pow(2, 3) + Math.pow(2, 5); // 判断2号是否签到 let day2 = Math.pow(2, 2); console.log((day2 & daySum) === day2); // false // 判断3号是否签到 let day3 = Math.pow(2, 3); console.log((day3 & daySum) === day3); // false
|
关于原理,用二进制来算,就一目了然了。
创建重复的字符串
1 2 3 4 5 6 7 8 9
| let repeat1 = ''; for (let i = 0; i < 7; i++) { repeat1 += 'a'; } console.log('repeat1=', repeat1); // aaaaaaa let repeat2 = Array(7).join('a'); console.log('repeat2=', repeat2); // aaaaaa let repeat3 = 'a'.repeat(7); // ES6写法 console.log('repeat3=', repeat3); // aaaaaaa
|
- 第三种写法是ES6的api,将字符串复制指定次数。
- 第二种写法是借助join的插入函数实现需求功能,这里其实不是很推荐,因为你打印repeat2会发现,其实只有6个a,因为join是在元素中插入,所以这里要实现复制7次就得创建一个8个元素的数组,一个字符串还要先创建一个数组,个人觉得没必要。
清空数组的操作
1 2 3 4 5
| let arr = [1,2,3]; // 第一种写法 arr = []; // 第二种写法 arr.length = 0;
|
两种写法有什么区别呢?
第一种写法其实是赋值一个新数组给变量aar,第二种写法是直接操作原数组。看下面例子
1 2 3 4 5 6 7 8 9
| let arr = [1, 2, 3]; let arr2 = arr; arr = []; console.log('arr=', arr); // [] console.log('arr2=', arr2); // [ 1, 2, 3 ] arr = arr2; arr2.length = 0; console.log('arr=', arr); // [] console.log('arr2=', arr2); // []
|
- 两种写法,很明显不能一棍子说优劣,但如果你的数组不需要使用了,自然应该使用Array.length=0的写法。
END
最后附赠JS社区玩坏的梗~
1 2
| console.log(([][[]] + [])[+!![]] + ([] + {})[!+[] + !![]]); console.log((!(~+[]) + {})[--[~+""][+[]] * [~+[]] + ~~!+[]] + ({} + [])[[~!+[]] * ~+[]]);
|
以上所有知识点皆来源于网络,各位有兴趣可以再去深入了解,如果发现本文有什么错误,可以后台给我留言。最后,非常感谢陈皮皮【公众号:菜鸟小栈】提供的几款VSCode的插件,真的好用!!!
原文链接: https://blog.xyzzlky.cn/posts/e06037f6/
版权声明: 转载请注明出处.