欢迎浏览我公司网站!!
行业资讯
可否举例说明你在工作中是如何优化前端代码的?
时间: 2024-06-04浏览次数:
比如利用新语法等方式精简代码,而非大量重复代码复制粘贴。首先说一个最重要的优化原则:代码优化是每天都要进行的,而不是一两个月做一次大优化,那时做就已经晚了。另外由于优化是每天做的,所以你不需要一次的就过度优化,保持小步快跑即可。这个原则为什么重要?因为很多程序员会在写代码的时候说「先不优化了,等不忙的时候再优化」,然后……就没有然后了。基本上「烂代码」就是因为「不忙的时候再优化」造

比如利用新语法等方式精简代码,而非大量重复代码复制粘贴。

首先说一个最重要的优化原则:代码优化是每天都要进行的,而不是一两个月做一次大优化,那时做就已经晚了。另外由于优化是每天做的,所以你不需要一次的就过度优化,保持小步快跑即可。


这个原则为什么重要?因为很多程序员会在写代码的时候说「先不优化了,等不忙的时候再优化」,然后……就没有然后了。


基本上「烂代码」就是因为「不忙的时候再优化」造成的。


如果只要每天优化一点点代码,就能保持你的程序健康,你,能做到吗?

据我观察,90% 的程序员做不到。他们每天都会在心里找出如下理由来写出烂代码,或者对现有的烂代码视而不见:

  1. 这个项目我只维护几个月,没必要把代码写那么好,反正有人接盘。
  2. 这个项目是从别人手里接下的,代码真烂,要怪就怪之前的人,不是我的错,我胡乱加一些代码就行了,能用就行。
  3. 这是一个短期项目,没必要把代码写那么好
  4. 这是一个长期项目,明年再优化代码,现在能用就行

所以你看,不管我告诉他们多少优化代码的技巧,他们根本就不会去用的,这才是问题所在。


很多程序员抱怨公司代码烂,却从来不去尝试解决问题。(就像很多程序员抱怨培训班教出来的人水平差,自己却不写新人教程一样)


如果你不想变成上面那样的程序员,你只坚定一个信念:只要是经过我的手的代码,质量就会比原来好一点。

那么你很快就能把代码写好了。你可能急于听到把代码写好的技巧,但是我告诉你,技巧真的不重要,这个信念才是最重要的。

接下来就是技巧。


方方你是傻了吗,问的是「如何优化代码」,你的答案居然是「不要写烂代码」?!

没错,把代码写好的第一步就是不要写烂代码,也就是你要知道「什么样的代码是烂代码」:

如何写出无法维护的代码 - 酷 壳 - CoolShell

上面这篇教程非常好,把市面上的烂代码基本都总结出来了,大概有这么几类:

  1. 烂变量名
  2. 烂注释
  3. 烂设计
  4. 不写测试(所有没有单元测试的代码都是烂代码,快点学习单元测试!)

基本上所有新人天天都在写烂变量名、烂注释和烂设计,而且还不写单元测试。

而且他们还不知道自己代码多烂!

所以第一步就是明白一个真相:你80%的代码都是烂代码。

你只需要把这些代码改得不那么烂,就是优秀的代码了……

再说一次:第一步至关重要,搞清楚什么样的代码是烂代码。


也就是 Don't Repeat Yourself 原则。如果你发现有两行代码重复出现了好几次,你就应该把这两行代码封装成一个函数,放在一个恰当的地方,然后调用这个函数。


如果你的代码有很多 if ... else ... 结构,你不知道怎么优化,你就应该使用表驱动编程。

优化前:

howManyDays(year, month){
    if(month === 1 ||
        month === 3 ||
        month === 5 ||
        month === 7 ||
        month === 8 ||
        month === 10 ||
        month === 12
    ){
        return 31
    }else if(month === 2){
        return isLeapYear(year) ? 29 : 28
    }else{
        return 30
    }
}

优化后:

howManyDays(year, month){
    const table = {
        1: 31, 3: 31, 5: 31, 7: 31, 8: 31, 10: 31, 12:31,
        4: 30, 6:30, 9: 30, 11: 30,
        2: isLeapYear(year) ? 29 : 28
    }
    return table[month]
}

优化前:

function calculateGrade(score){
    if(score>=90){
        return 'A'
    }else if(score >= 80){
        return 'B'
    }else if(score >= 70){
        return 'C'
    }else if(score >= 60){
        return 'D'
    }else {
        return 'E'
    }
}

优化后:

function calculateGrade(score){
    const table = {
        100: 'A', 
        90: 'A',
        80: 'B',
        70: 'C',
        60: 'D',
        others: 'E'
    }
    return table[Math.floor(score/10)*10] || table['others']
}    

设计模式就是一些编程套路,Unix 编程原则也是一些编程套路。

了解所有的套路,然后遇到问题选择正确的套路即可。

比如模块通信一般用事件模式或者命令模式;

比如解耦一般用中间层;

比如生命周期一般都支持钩子或切面;

比如性能优化一般都是加缓存;

比如 API 设计一定要正交;

比如复杂数据系统一般使用命令查询职责分离;

比如拿空间换时间拿时间换空间;

……

这一块还挺复杂的,够你纠结很久了,而且没有通解。唯一的通解就是 tradeoff。


我在课上说过,「每天优化」才叫重构,「每年优化」那叫重写。

优化的重点是「越来越好」,重点不是「一次写好」。

一旦你放松对自己代码的要求,你的代码就会迅速变成烂代码,而且很难恢复。

每当需求变化的时候,你都要重新审视你的整个系统,哪里有问题你就改那里,不允许「先临时改一下以后再优化」,你的代码就可以保持健康和活力。


可惜,大部分人做不到。就算我自己也会在需求太多的时候放松对代码的要求。


以上内容在我的《JS深入浅出》课程中有所涉及,课程讲义可以免费看

为一部分自己的代码配.d.ts算吗……

如果是接手老代码,一个比较有可行性的办法是,尽量把自己的代码和老代码隔离开。如果有引用,则想办法把接口局限在某个领域内,最好是为它准备个注入机制,随时留“这破玩意要换”的后手……

然后就是,就算是相同的业务,也总是写着写着就想到点小花招是吧……会考虑逐步改旧的实现吗?(当然,反正我不会)

从个人角度来说,养成良好的开发习惯,在项目开始时就准备好eslint、tslint、stylelint...以及单元测试等,能用ts的项目最好用ts,lint规则不要随便从网上扒,自己查一下官网或github,能打开的规则都要打开,程序员就得对自己狠一点。

从团队来说,把各种lint推行下去,然后定期codereview。

具体到编码层面,太细致了没办法面面俱到,自己多看点相关文章吧,如果可以,研究一下浏览器实现是最吼的。



另外补充一个重要的点——

会读你写过的代码的只有两个物种:程序员和浏览器。所以,优化其实也是分两个方向的!

在浏览器性能和代码可读性之间,往往需要做出取舍。这一点在“优化”的时候一定要想清楚,如果是长期维护的项目,那可读性肯定要优于性能;如果是一次性的项目,追求一下性能的极致也是很好的。

1、养成持续重构的习惯。

2、学习重构的技巧,手法,具体可能参照最新版的《重构》一书。

3、寻找最佳实践去尝试,可以从身边优秀的同事,或者社区获取。

每当我在网上浏览到大神的代码,我就
常常因自己功能实现的不够巧妙而羞愧
又因自己代码书写的不够优雅而悔恨
不禁让我想起来雷军的那段经典
提问:写过诗吗?
雷总:我没有写过诗,但是有人说我写过的代码,像诗一样优雅!

感兴趣的可以在我们第二Part文章里面看看,雷总究竟是怎么让代码优雅成了诗的。

今天我们就给大家的介绍18种让你的JavaScript代码优雅起来的方法。

const arr=[1, 2, 3]; 
Math.max(…arr); // 3
Math.min(…arr); // 
let str='abc';
//Longhand 
str.charAt(2); // c
//Shorthand 
str[2]; // c

这个方法可以将对象转换为对象数组

const data={ test1: 'abc', test2: 'cde', test3: 'efg' };
const arr=Object.entries(data);
console.log(arr);
/** Output:
[[ 'test1', 'abc' ],
[ 'test2', 'cde' ],
[ 'test3', 'efg' ]
]
**/

如果我们要基于不同的类型调用不同的方法,可以使用多个 else if 语句或 switch,但有没有比这更好的简化技巧呢

// Longhand
if (type==='test1'){
  test1();
}
else if (type==='test2'){
  test2();
}
else if (type==='test3'){
  test3();
}
else if (type==='test4'){
  test4();
}else{
  throw new Error('Invalid value ' + type);
}
// Shorthand
var types={
  test1: test1,
  test2: test2,
  test3: test3,
  test4: test4
};
var func=types[type];
(!func) && throw new Error('Invalid value ' + type); func();

当我们有一个对象数组,并想根据对象属性找到特定对象,find 方法会非常有用。

const data=[{
        type: 'test1',
        name: 'abc'
    },
{
        type: 'test2',
        name: 'cde'
    },
{
        type: 'test1',
        name: 'fgh'
    },
]
function findtest1(name){
    for (let i=0; i < data.length; ++i){
        if (data[i].type==='test1' && data[i].name===name){
            return data[i];
        }
    }
}
//Shorthand
filteredData=data.find(data=> data.type==='test1' && data.name==='fgh');
console.log(filteredData); //{ type: 'test1', name: 'fgh' }

当我们在代码中处理跨行字符串时,可以这样做。

//longhand
const data='abc abc abc abc abc abc\
\	'
    + 'test test,test test test test\
\	'
//shorthand
const data=`abc abc abc abc abc abc
         test test,test test test test`

7、将字符串转成数字

//Longhand 
let test1=parseInt('123'); 
let test2=parseFloat('12.3'); 
//Shorthand 
let test1=+'123'; 
let test2=+'12.3';

8、解构赋值

//longhand
const test1=this.data.test1;
const test2=this.data.test2;
const test2=this.data.test3;
//shorthand
const{ test1, test2, test3 }=this.data;


9、模板字面量
如果你厌倦了使用 + 将多个变量连接成一个字符串,那么这个简化技巧将让你不再头痛。

//longhand
const welcome='Hi ' + test1 + ' ' + test2 + '.'
//shorthand
const welcome=`Hi ${test1}${test2}`;


10、延展操作符简化

//longhand
// 使用concat连接数组
const data=[1, 2, 3];
const test=[4 ,5 , 6].concat(data);
//shorthand
// 连接数组
const data=[1, 2, 3];
const test=[4 ,5 , 6, ...data];
console.log(test); //[ 4, 5, 6, 1, 2, 3]


我们也可以使用延展操作符进行克隆。

//longhand
// 克隆数组
const test1=[1, 2, 3];
const test2=test1.slice()
//shorthand
//克隆数组
const test1=[1, 2, 3];
const test2=[...test1];



11、默认参数值

//Longhand
function add(test1, test2){
  if (test1===undefined)
    test1=1;
  if (test2===undefined)
    test2=2;
  return test1 + test2;
}
//shorthand
add=(test1=1, test2=2)=> (test1 + test2);
add() //输出结果: 3



12、 指数表示法

// Longhand
for (var i=0; i < 10000; i++){ ... }
// Shorthand
for (var i=0; i < 1e4; i++){



13、隐式返回
通过使用箭头函数,我们可以直接返回值,不需要 return 语句。

//longhand
function calculate(diameter){
  return Math.PI * diameter
}
//shorthand
calculate=diameter=> (
  Math.PI * diameter;
)



14、switch 简化
我们可以将条件保存在键值对象中,并根据条件来调用它们。

// Longhand
switch (data){
  case 1:
    test1();
  break;
  case 2:
    test2();
  break;
  case 3:
    test();
  break;
  // ...
}
// Shorthand
var data={
  1: test1,
  2: test2,
  3: test
};
data[something]&& data[something]();



15、简短的函数调用
我们可以使用三元操作符来实现多个函数调用。

// Longhand
function test1(){
  console.log('test1');
};
function test2(){
  console.log('test2');
};
var test3=1;
if (test3==1){
  test1();
}else{
  test2();
}
// Shorthand
(test3===1? test1:test2)();



16、for each 循环
这是一种常见的循环简化技巧。

// Longhand
for (var i=0; i < testData.length; i++)
// Shorthand
for (let i in testData) or  for (let i of testData)


遍历数组的每一个变量。

function testData(element, index, array){
  console.log('test[' + index + ']=' + element);
}
[11, 24, 32].forEach(testData);
// logs: test[0]=11, test[1]=24, test[2]=32


17、 用于多个条件判断的 && 操作符
如果只在变量为 true 时才调用函数,可以使用 && 操作符。

//Longhand 
if (test1){
 callMethod(); 
}
//Shorthand 
test1 && callMethod();


18、简化 if true...else
对于不包含大逻辑的 if-else 条件,可以使用下面的快捷写法。我们可以简单地使用三元运算符来实现这种简化。

// Longhand
let test: boolean;
if (x > 100){
    test=true;
}else{
    test=false;
}
// Shorthand
let test=(x > 10) ? true : false;
//或者我们也可以直接用
let test=x > 10;
console.log(test);


如果有嵌套的条件,可以这么做。

let x=300,
test2=(x > 100) ? 'greater than 100' : (x < 50) ? 'less 50' : 'between 50 and 100';
console.log(test2); // "greater than 100"


Copyright © 2002-2022 盛煌-盛煌娱乐-盛煌全球注册认证站 版权所有

粤IP*******

平台注册入口