翼度科技»论坛 编程开发 JavaScript 查看内容

JS优化技巧,解决冗余代码

6

主题

6

帖子

18

积分

新手上路

Rank: 1

积分
18
1. 使用箭头函数简化函数定义
  1. // 传统函数定义
  2. function add(a, b) {
  3. return a + b;
  4. }
  5.   
  6. // 箭头函数简化
  7. const add = (a, b) => a + b;
复制代码
2. 使用解构赋值简化变量声明
  1. // 传统变量声明
  2. const firstName = person.firstName;
  3. const lastName = person.lastName;
  4. // 解构赋值简化
  5. const { firstName, lastName } = person;
复制代码
3. 使用模板字面量进行字符串拼接
  1. // 传统字符串拼接
  2. const greeting = 'Hello, ' + name + '!';
  3. // 模板字面量简化
  4. const greeting = `Hello, ${name}!`;
复制代码
4. 使用展开运算符进行数组和对象操作
  1. // 合并数组
  2. const combined = [...array1, ...array2];
  3. // 复制对象
  4. const clone = { ...original };
复制代码
5. 使用数组的高阶方法简化循环和数据操作
  1. // 遍历数组并返回新数组
  2. const doubled = numbers.map(num => num * 2);
  3. // 过滤数组
  4. const evens = numbers.filter(num => num % 2 === 0);
复制代码
6. 使用条件运算符简化条件判断
  1. // 传统条件判断
  2. let message;
  3. if (isSuccess) {
  4. message = 'Operation successful';
  5. } else {
  6. message = 'Operation failed';
  7. }
  8. // 条件运算符简化
  9. const message = isSuccess ? 'Operation successful' : 'Operation failed';
复制代码
7. 使用对象解构和默认参数简化函数参数
  1. // 传统参数设置默认值
  2. function greet(name) {
  3. const finalName = name || 'Guest';
  4. console.log(`Hello, ${finalName}!`);
  5. }
  6.   
  7. // 对象解构和默认参数简化
  8. function greet({ name = 'Guest' }) {
  9. console.log(`Hello, ${name}!`);
  10. }
复制代码
8. 使用函数式编程概念如纯函数和函数组合
  1. // 纯函数
  2. function add(a, b) {
  3. return a + b;
  4. }
  5.   
  6. // 函数组合
  7. const multiplyByTwo = value => value * 2;
  8. const addFive = value => value + 5;
  9. const result = addFive(multiplyByTwo(3));
复制代码
9. 使用对象字面量简化对象的创建和定义
  1. // 传统对象创建
  2. const person = {
  3. firstName: 'John',
  4. lastName: 'Doe',
  5. age: 30,
  6. };
  7.   
  8. // 对象字面量简化
  9. const firstName = 'John';
  10. const lastName = 'Doe';
  11. const age = 30;
  12. const person = { firstName, lastName, age };
复制代码
10. 使用适当的命名和注释来提高代码可读性
  1. // 不好的
  2. const x = 10; // 设置x的值为10
  3. function a(b) {
  4. return b * 2; // 返回b的两倍
  5. }
  6. // 好的
  7. const speed = 10; // 设置速度为10
  8. function double(value) {
  9. return value * 2; // 返回输入值的两倍
复制代码
11. 优雅的写条件判断代码

简单的条件判断逻辑用if else 或者 三元运算符, 一眼看过去还能知道说的啥,但是大量的if else和叠加在一起的三元运算符就是接盘侠的噩梦~~~
给大家上一个三元运算符叠加的案例,我是真实在项目中遇到过,cpu直接干爆~~~
  1. <view>{{status===1?'成功': status===2 ? '失败' : status===3 ? '进行中' : '未开始' }}</view>
复制代码
大概是这样的,具体的项目代码不好放在这里,小伙伴们意会就行。
复杂逻辑推荐使用对象Map写法,符合人脑的逻辑,可读性高,看着舒服~~~
1,普通的if else
  1. let txt = '';
  2. if (falg) {
  3. txt = "成功"
  4. } else {
  5. txt = "失败"
  6. }
复制代码
2,三元运算符
  1. let txt = flag ? "成功" : "失败";
复制代码
3,多个if else
  1. // param {status} status 活动状态:1:成功 2:失败 3:进行中 4:未开始
  2. let txt = '';
  3. if (status == 1) {
  4. txt = "成功";
  5. } else if (status == 2) {
  6. txt = "失败";
  7. } else if (status == 3) {
  8. txt = "进行中";
  9. } else {
  10. txt = "未开始";
  11. }
复制代码
4,switch case
  1. let txt = '';
  2. switch (status) {
  3. case 1:
  4. txt = "成功";
  5. break;
  6. case 2:
  7. txt = "成功";
  8. break;
  9. case 3:
  10. txt = "进行中";
  11. break;
  12. default:
  13. txt = "未开始";
  14. }
复制代码
5,对象写法
  1. const statusMap = {
  2. 1: "成功",
  3. 2: "失败",
  4. 3: "进行中",
  5. 4: "未开始"
  6. }
  7. //调用直接 statusMapp[status]
复制代码
5,Map写法
  1. const actions = new Map([
  2. [1, "成功"],
  3. [2, "失败"],
  4. [3, "进行中"],
  5. [4, "未开始"]
  6. ])
  7. // 调用直接 actions.get(status)
复制代码
12. 封装条件语句

同上,if里的条件越多越不利于接盘侠的维护,不利于人脑的理解,一眼看过去又是一堆逻辑。多个逻辑应该化零为整。
  1. 大脑:'别来碰我,让我静静'
  2. // 不好的
  3. if (fsm.state === 'fetching' && isEmpty(listNode)) {
  4. // ...
  5. }
  6. // 好的
  7. shouldShowSpinner(fsm, listNode){
  8. return fsm.state === 'fetching' && isEmpty(listNode)
  9. }
  10. if(shouldShowSpinner(fsm, listNode)){
  11. //...doSomething
  12. }
复制代码
13. 函数应该只做一件事

函数式写法推崇柯里化, 一个函数一个功能,可拆分可组装。
  1. // 不好的
  2. function createFile(name, temp) {
  3. if (temp) {
  4.    fs.create(`./temp/${name}`);
  5. } else {
  6.    fs.create(name);
  7. }
  8. }
  9. // 好的
  10. function createFile(name) {
  11. fs.create(name);
  12. }
  13. function createTempFile(name) {
  14. createFile(`./temp/${name}`)
  15. }
复制代码
再来一个栗子
函数要做的事情如下:

  • 遍历clients数组
  • 遍历过程中,通过lookup函数得到一个新的对象clientRecord
  • 判断clientRecord对象中isActive函数返回的是不是true,


    • isActive函数返回true,执行email函数并把当前成员带过去

  1. // 不好的
  2. function emailClients(clients) {
  3. clients.forEach((client) => {
  4.    const clientRecord = database.lookup(client);
  5.    if (clientRecord.isActive()) {
  6.      email(client);
  7.    }
  8. });
  9. }
  10. // 好的
  11. function emailClients(clients) {
  12. clients
  13.    .filter(isClientRecord)
  14.    .forEach(email)
  15. }
  16. function isClientRecord(client) {
  17. const clientRecord = database.lookup(client);
  18. return clientRecord.isActive()
  19. }
复制代码
上面不好的栗子一眼看过去是不是感觉一堆代码在那,一时半会甚至不想去看了。
好的栗子,是不是逻辑很清晰,易读。

  • 巧用filter函数,把filter的回调单开一个函数进行条件处理,返回符合条件的数据
  • 符合条件的数据再巧用forEach,执行email函数
14. Object.assign给默认对象赋默认值
  1. // 不好的
  2. const menuConfig = {
  3. title: null,
  4. body: 'Bar',
  5. buttonText: null,
  6. cancellable: true
  7. };
  8. function createMenu(config) {
  9. config.title = config.title || 'Foo';
  10. config.body = config.body || 'Bar';
  11. config.buttonText = config.buttonText || 'Baz';
  12. config.cancellable = config.cancellable === undefined ?
  13. config.cancellable : true;
  14. }
  15. createMenu(menuConfig);
  16. // 好的
  17. const menuConfig = {
  18. title: 'Order',
  19. buttonText: 'Send',
  20. cancellable: true
  21. };
  22. function createMenu(config) {
  23. Object.assign({
  24.    title: 'Foo',
  25.    body: 'Bar',
  26.    buttonText: 'Baz',
  27.    cancellable: true
  28. }, config)
  29. }
  30. createMenu(menuConfig);
复制代码
15. 函数参数两个以下最好

说一千道一万,就是为了优雅,就是为了可读性好。
  1. // 不好的
  2. function createMenu(title, body, buttonText, cancellable) {
  3. // ...
  4. }
  5. // 好的
  6. const menuConfig = {
  7. title: 'Foo',
  8. body: 'Bar',
  9. buttonText: 'Baz',
  10. cancellable: true
  11. };
  12. function createMenu(config){
  13. // ...
  14. }
  15. createMenu(menuConfig)
复制代码
16. 使用解释性的变量

省流,用了扩展运算符,为了可读性(saveCityZipCode(city, zipCode)可读性很好,知道参数是干嘛的)
  1. // 不好的
  2. const address = 'One Infinite Loop, Cupertino 95014';
  3. const cityZipCodeRegex = /^[^,\\]+[,\\\s]+(.+?)\s*(\d{5})?$/;
  4. saveCityZipCode(address.match(cityZipCodeRegex)[1], address.match(cityZipCodeRegex)[2]);
  5. // 好的
  6. const address = 'One Infinite Loop, Cupertino 95014';
  7. const cityZipCodeRegex = /^[^,\\]+[,\\\s]+(.+?)\s*(\d{5})?$/;
  8. cosnt [, city, zipCode] = address.match(cityZipCodeRegex) || [];
  9. saveCityZipCode(city, zipCode)
复制代码
想对类中的属性进行更多自定义取/增/改的操作时,使用set/get
第一次见这个写法,不知道是啥意思的小伙伴,把他当成vue2中的defineProperty
  1. Object.defineProperty(data1,'age',{
  2. set:function(newAge){
  3.    console.log(this.name+'现在'+newAge+'岁')
  4. },
  5. get:function(){
  6.    return 18;
  7. }
  8. })
复制代码
是一个意思,赋值的时候set会被触发,取值的时候get会被触发。
巧用自带属性,提升性能。
  1. class BankAccount {
  2. constructor(balance = 1000) {
  3.    this._balance = balance;
  4. }
  5. // It doesn't have to be prefixed with `get` or `set` to be a
  6. //getter/setter
  7. set balance(amount) {
  8.    console.log('set')
  9.    if (verifyIfAmountCanBeSetted(amount)) {
  10.      this._balance = amount;
  11.    }
  12. }
  13. get balance() {
  14.    console.log('get')
  15.    return this._balance;
  16. }
  17. verifyIfAmountCanBeSetted(val) {
  18.    // ...
  19. }
  20. }
  21. const bankAccount = new BankAccount();
  22. // Buy shoes...
  23. bankAccount.balance -= 100;
  24. // Get balance
  25. let balance = bankAccount.balance;
复制代码
17. 让对象拥有私有成员-通过闭包来实现

闭包天生就是做私有化的
  1. // 不好的
  2. const Employee = function(name) {
  3. this.name = name;
  4. };
  5. Employee.prototype.getName = function getName() {
  6. return this.name;
  7. };
  8. const employee = new Employee('John Doe');
  9. console.log(`Employee name: ${employee.getName()}`); // Employee name: John Doe
  10. delete employee.name;
  11. console.log(`Employee name: ${employee.getName()}`); // Employee name: undefined
  12. // 好的
  13. const Employee = function(name){
  14. this.getName = function(){
  15.    return name
  16. }
  17. }
  18. const employee = new Employee('John Doe');
  19. console.log(`Employee name: ${employee.getName()}`); // Employee name: John Doe
  20. delete employee.name;
  21. console.log(`Employee name: ${employee.getName()}`); // Employee name: undefined
复制代码
第一个示例
优点:

  • 通过原型链共享方法,节省了内存空间。所有实例对象共享同一个 getName 方法,而不是每个实例对象都创建一个独立的方法。
缺点:

  • 在构造函数中无法直接定义私有属性或方法,所有属性和方法都会被暴露在原型链上。
第二个示例
优点:

  • 可以在构造函数内部定义私有属性和方法,不会暴露在对象的原型链上,提供了更好的封装性。
缺点:

  • 每次创建实例对象时,都会创建一个独立的方法,每个实例对象都有自己的 getName 方法,占用更多的内存空间。
18. 使用方法链

链式写法也是代码优雅之道的重头戏。
ps:发明这个的程序员肯定是后端出身的,这种写法在PHP的CI框架中见过。
  1. // 不好的
  2. class Car {
  3. constructor() {
  4.    this.make = 'Honda';
  5.    this.model = 'Accord';
  6.    this.color = 'white';
  7. }
  8. setMake(make) {
  9.    this.make = make;
  10. }
  11. save() {
  12.    console.log(this.make, this.model, this.color);
  13. }
  14. }
  15. const car = new Car();
  16. car.setMake('Ford');
  17. car.save();
  18. // 好的
  19. class Car {
  20. constructor() {
  21.    this.make = 'Honda';
  22.    this.model = 'Accord';
  23.    this.color = 'white';
  24. }
  25. setMake(make) {
  26.    this.make = make;
  27.    // NOTE: return this是为了用链式写法
  28.    return this;
  29. }
  30. save() {
  31.    console.log(this.make, this.model, this.color);
  32.    // NOTE:return this是为了用链式写法
  33.    return this;
  34. }
  35. }
  36. const car = new Car()
  37. .setMake('Ford')
  38. .save();
复制代码
看完上面的这么多栗子,小伙伴的思路是不是清晰了很多,在你们的项目里练练手吧。

来源:https://www.cnblogs.com/xw-01/p/17600393.html
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

举报 回复 使用道具