JS代码优化(上篇)
目录
1、按强类型风格写代码
(1)定义变量时指明数据类型
- 定义变量时给默认值,方便JS解析器,也方便阅读人
var num = 0,
str = '',
obj = null;
(2)不要随意地改变变量的类型,需要更改就创建新变量赋值
//bad 整型变成字符串类型,js最终会解释成为汇编语言,就会做额外处理
var num = 5;
num = "-" + num;
//best
var num = 5;
var sign = "-" + num;
(3)函数的返回类型应该是要确定的
//bad 返回类型要确定,不能一下是字符串,一下是数字。 字符串与数值运算:NaN
function getPrice(count){
if(count < 0) return "";
else return count * 100;
}
//best 返回-1表示不合法,类型确定的话,JS解释器就不会做额外工作,可加快运行速度
function getPrice(count){
if(count < 0) return -1;
else return count * 100;
}
2、减少作用域的查找
(1)不要让代码暴露在全局作用域下,弄成一个局部的作用域
//bad script 标签里面,代码的上下文都是全局作用域的
<script>
var map = document.querySelector("#my-map");
map.style.height = "600px";
</script>
//best function 制造一个局部作用域,也可以用 ES6 的块级作用域
// 局部作用域的查找是很快的。同时直接在全局作用域定义变量,会污染 window 对象。
<script>
!function(){
var map = document.querySelector("#my-map");
map.style.height = "600px";
}()
</script>
(2)不要滥用闭包
- 闭包的作用在于可以让子级作用域使用它父级作用域的变量,同时这些变量在不同的闭包是不可见的。
//bad 在查找某个变量的时候,如果当前作用域找不到,就得往它的父级作用域查找,
//一级一级地往上直到找到了,或者到了全局作用域还没找到。闭包嵌套越深,查找时间越长
function getResult(count){
count++;
function process(){
var factor = 2;
return count * factor - 5;
}
return process();
}
//best 闭包的count变量直接传递过去 process(count)
function getResult(count){
count++;
function process(count){
var factor = 2;
return count * factor - 5;
}
return process(count);
}
(3)全局变量频繁使用时,可用局部变量缓存一下
//bad window.location 全局变量,查找就会缓慢
var url = "";
if(window.location.protocal === "https:"){
url = "wss://xxx.com" + window.location.pathname + window.location.search;
}
//best
//频繁地使用了 window.location 对象,先缓存一个局部变量,查找快于全局查找,代码也少点
var url = "";
var location = window.location;
if(location.protocal === "https:"){
url = "wss://xxx.com" + location.pathname + location.search;
}
3、避免 == 的使用
(1)如果你确定了变量的类型,就使用 === 来替换 ==
// 一个是字符串,一个是整数 ,直接用===
if(typeof num != "undefined"){ }
var num = parseInt(value);
if(num == 10){ }
(2)如果类型不确定,手动类型转换,别让别人或自己猜这里有类型转换
var totalPage = "5";
if(parseInt(totalPage) === 1){ }
(3)使用==在 JSLint 检查的时候是不通过的
if(a == b){ }
//JSLint下会输出
Expected ‘===’ and instead saw ‘==’.
if(a == b){}
(4)使用==可能会出现一些奇怪的现象,这些奇怪的现象可能会给代码埋入隐患
null == undefined //true
'' == '0' //false
0 == '' //true
0 == '0' //true
'' == 0 //true
new String("abc") == "abc" //true
new Boolean(true) == true //true
true == 1 //true
/*上面的比较在用===的时候都是 false,这样才是比较合理的。
null == undefined //true 特别地奇怪
null 和 undefined //是两个毫无关系的值
null 应该是作为初始化空值使用
undefined 是用于检验某个变量是否未定义
*/
4、合并表达式
- 如果用 1 句代码就可以实现 5 句代码的功能,那往往 1 句代码的执行效率会比较高,并且可读性可能会更好。
(1)用三目运算符取代简单的 if-else
//bad
function getPrice(count){
if(count < 0) return -1;
else return count * 100;
}
//best 如果写了if-else ,压缩工具也会帮你改成三目运算符形式
function getPrice(count){
return count < 0 ? return -1 : count * 100;
}
//压缩形式:
function getPrice(e){return 0>e?-1:100*e}
(2)使用连等
//连等是利用赋值运算表达式会返回所赋的值,并且执行顺序是从右到左的
overtime = favhouse = listingDetail = {...}
//用了赋值表达式会返回一个值,再进行判断,+号把字符串转成了整数
var age = 0;
if((age = +form.age.value) >= 18){
console.log("你是成年人");
} else {
consoe.log("小朋友,你还有" + (18 - age) + "就成年了");
}
(3)利用自增
//利用自增也可以简化代码。如下,每发出一条消息,localMsgId 就自增 1
chatService.sendMessage(localMsgId++, msgContent);
5、减少魔数
/上面的四个常量分别代表什么呢?不去查就不知道有什么用,这些意义不明的常量就叫“魔数”
dialogHandler.showQuestionNaire("seller", "sell", 5, true);
//best 给常量取个名字,这样就很清楚了
var naireType = "seller",
dialogType = "sell",
questionsCount = 5,
reloadWindow = true;
naireHandler.showNaire(naireType, dialogType, questionsCount, reloadWindow);
6、使用ES6简化代码
- ES6 已经发展很多年了,兼容性也已经很好了。恰当地使用,可以让代码更加地简洁优雅。
(1)使用箭头函数取代小函数(数组从大到小排序)
// JS的sort 方法
var nums = [4, 8, 1, 9, 0];
nums.sort(function(a, b){
return b - a;
});
//输出[9, 8, 4, 1, 0]
// ES6 箭头函数排序一行搞定
var nums = [4, 8, 1, 9, 0];
``nums.sort(a, b => b - a);
nums.sort((a, b) => b - a); //输出[9, 8, 4, 1, 0]
//延时器
setTimeout(() => console.log("hi"), 3000)
(2)使用 ES6 的 class
function Person(name, age){
this.name = name;
this.age = age;
}
Person.prototype.addAge = function(){
this.age++;
};
Person.prototype.setName = function(name){
this.name = name;
};
// class 还可以很方便地实现继承、静态的成员函数,就不需要自己再去通过一些技巧去实现了。
class Person{
constructor(name, age){
this.name = name;
this.age = age;
}
addAge(){
this.age++;
}
setName(name){
this.name = name;
}
}
- 虽然 ES6 的 class 和使用 function 的 prototype 本质上是一样的,都是用的原型。但是用 class 可以减少代码量,同时让代码看起来更加地高大上。
(3)字符串拼接
//以前要用+号拼接
var tpl =
'<div>' +
' <span>1</span>' +
'</div>';
//现在只要用两个反引号“`”就可以了
var tpl =
` <div>
<span>1</span>
</div>
`;
//反引号还支持占位替换
//原本写法
var page = 5,
type = encodeURIComponet("#js");
var url = "/list?page=" + page + "&type=" + type;
//反引号写法 就不用使用+号把字符串拆散了
var url = `/list?page=${page}&type=${type}`;
7、代码净化
(1)注重命名
//bad
function mergeNumberListIntoUniqueList(listOne, listTwo) {
return [...new Set([...listOne, ...listTwo])]
}
//best
function mergeLists(listOne, listTwo) {
return [...listOne, ...listTwo]
}
function createUniqueList(list) {
return [...new Set(list)]
}
(2)IF语句优化
//bad
if(value === 'duck' || value === 'dog' || value === 'cat') {
// ...
}
//best 将乱七八糟的条件判断放到一个变量中存储,比看臃肿的表达式要好很多
const options = ['duck', 'dog', 'cat'];
if (options.includes(value)) {
// ...
}
(3)及早返回
//bad
function handleEvent(event) {
if (event) {
const target = event.target;
if (target) {
// Your awesome piece of code that uses target
}
}
}
//best
function handleEvent(event) {
if (!event || !event.target) {
return;
}
// Your awesome piece of code that uses target
}
(4)解构赋值
// object 解构赋值
const numbers = {one: 1, two: 2};
const {one, two} = numbers;
console.log(one); // 1
console.log(two); // 2
// array 解构赋值
const numbers = [1, 2, 3, 4, 5];
const [one, two] = numbers;
console.log(one); // 1
console.log(two); // 2
(5)童子军规则
- 童子军有一条规则:永远保持离开时的露营比你发现它时更整洁。如果你在地面上发现了脏东西,那么无论是否是你留下的,你都要将它清理干净。你要有意地为下一组露营者改善环境。
- 我们编写代码也是这样子,如果你在代码中发现了脏代码,那么你可以尝试去修改它,即使是一个没有被引用到的变量名。
(6)代码风格
- 在你的团队中使用一种代码风格,比如限定代码缩进的规范是两空格呢还是四空格;使用单引号呢还是双引号呢;使用同类的一种框架呢,还是流行两种解决方案的框架呢...这样团队中人员接手项目的成本就会降低,开发人员的心里减少排斥感~