如何让你的代码变得更优雅?这些代码规范和技巧必须知道(进阶必备,建议收藏)下

简介: 笔记

5. 函数优化


5.1 提炼函数


在javascript开发中,大部分时间都在与函数打交道,所以希望这些函数有着良好的命名,函数体内包含的逻辑清晰明了。

如果一个函数过长,不得不加上若干注释才能让这个函数显得易读一些,那这些函数就很有必要进行重构

如果在函数中有一段代码可以被独立出来,那最好把这些代码放进另外一个独立的函数中,这是一种很常见的优化工作。

项目越大,必须拆分得越细,好维护(函数也是如此)

千万不要一个函数从奶奶家写到外婆家去了

这样做的好处主要有以下几点:


避免出现超大函数

独立出来的函数有助于代码复用

独立出来的函数更容易被覆写

独立出来的函数如果拥有一个良好的命名,它本身就起到了注释的作用

比如在一个负责取得用户信息的函数里面,还需要打印跟用户信息有关的信息,那么打印的语句就可以被封装在一个独立的函数里:

let getUserInfo = function(){
    ajax( 'http:// xxx.com/userInfo', function( data ){
        console.log( 'userId: ' + data.userId );
        console.log( 'userName: ' + data.userName );
        console.log( 'nickName: ' + data.nickName );
    });
};
//改成:
let getUserInfo = function(){
    ajax( 'http:// xxx.com/userInfo', function( data ){
        printDetails( data );
    });
};
let printDetails = function( data ){
    console.log( 'userId: ' + data.userId );
    console.log( 'userName: ' + data.userName );
    console.log( 'nickName: ' + data.nickName );
};

5.2 尽量减少参数


调用一个函数时需要传入多个参数,那这个函数是让人望而生畏的(甚至调用起来还会骂娘~)

必须搞清楚这些参数代表的含义,必须小心翼翼地把它们按照顺序传入该函数。

在实际开发中,向函数传递参数不可避免,但应该尽量减少函数接收的参数数量

比如我们需要封装一个CSS操作库:


第一版的代码

function cssTransform(ele, attr, val){
    // ele 要操作的元素
    // attr 运动属性 缩放,旋转
    // val 具体值
    if(!ele.transform){
        ele.transform = {};
    }
    if(typeof val === "undefined"){
        // 取值阶段
        // 取不到 设置默认值
        if(typeof ele.transform[attr] === "undefined"){
            switch(attr){
                case "scale":
                case "scaleX":    
                case "scaleY":    
                case "scaleZ":
                    // attr是scale 默认值是1 其它都是0
                    ele.transform[attr] = 1;
                    break;   
                default:
                    ele.transform[attr] = 0;     
            }
        }
        // 取值完毕 返回该值
        return ele.transform[attr];
    }else{
        // 赋值阶段
        ele.transform[attr] = val;      // 设置属性 方便取值
        let transformVal = "";
        for(var s in ele.transform){
            switch(s){
                case "scale":
                case "scaleX":    
                case "scaleY":    
                case "scaleZ":
                    transformVal += " " + s + "("+(ele.transform[s])+")";
                    break;
                case "rotate":
                case "rotateX":    
                case "rotateY": 
                case "rotateZ": 
                case "skewX":
                case "skewY":    
                    transformVal += " " + s + "("+(ele.transform[s])+"deg)";
                    break;
                default:
                    transformVal +=  " " + s + "("+(ele.transform[s])+"px)";    
            }
            ele.style.WebkitTransform = ele.style.transform = transformVal;
        }
    }
}
  • 我们需要传入三个参数,这就导致了传参的复杂性
  • 可以将它绑定到HTML元素上,减少传参
HTMLElement.prototype.cssTransform = function (prop, value){
    var transform,
        transformValue = "";
        if(this.transform === undefined) {
            this.transform = transform = Object.create(null);
        }
        if(value !== undefined){
            // 赋值阶段
            this.transform[prop] = value;
            transform = this.transform;
            for(var name in transform){
                switch(name){
                    case "scale":
                    case "scaleX":    
                    case "scaleY":    
                    case "scaleZ":
                        transformValue += " " + name + "("+ transform[name]+")";
                        break;
                    case "rotate":
                    case "rotateX":    
                    case "rotateY": 
                    case "rotateZ": 
                    case "skewX":
                    case "skewY":    
                        transformValue += " " + name + "("+ transform[name] + "deg)";
                        break;
                    default:
                        transformValue +=  " " + name + "("+ transform[name] + "px)";    
                }
                this.style.WebkitTransform = this.style.transform = transformValue;
            }
        }else{
            // 取值
            return this.transform[prop];
        }
}
  • 现在就只需要两个参数了
  • 核心代码没变,事件直接绑定在元素上,每一个html都拥有这个原型方法
  • 调用更加方便,传参更加简单60.png


6.条件优化


6.1 合并条件判断


如果一个函数体内有一些条件分支语句,而这些条件分支语句内部散布了一些重复的代码,那么就有必要进行合并去重工作。

假如有一个分页函数paging(),该函数接收一个参数currPage,currPage表示即将跳转的页码。

在跳转之前,为防止currPage传入过小或者过大的数字,要手动对它的值进行修正,详见如下代码

let paging = function( currPage ){
    if ( currPage == 0 ){
        currPage = 0;
        jump( currPage ); // 跳转
    }else if ( currPage == totalPage ){
        currPage = totalPage;
        jump( currPage ); // 跳转
    }else{
        jump( currPage ); // 跳转
    }
};
  • 可以看到,负责跳转的代码jump(currPage)在每个条件分支内都出现了,所以完全可以把这句代码独立出来
let paging = function( currPage ){
    if ( currPage == 0 ){
        currPage = 0;
    }else if ( currPage == totalPage ){
        currPage = totalPage;
    }
    jump( currPage ); // 把jump 函数独立出来
};

6.2 条件语句过多,提炼成函数

  • 在程序设计中,复杂的条件分支语句是导致程序难以阅读和理解的重要原因,而且容易导致一个庞大的函数
  • 假设现在有一个需求是编写一个计算商品价格的 getPrice(),商品的计算只有一个规则:如果当前正处于夏季,那么所有冬装将以5折出售
let getPrice = function( price ){
    let date = new Date();
    if ( date.getMonth() > 6 &&  date.getMonth() < 10 ){ // 冬天
        return price * 0.5;
    }
    return price;
};
  • 判断是否处于夏季
if ( date.getMonth() > 6 &&  date.getMonth() < 10 )

这句代码要表达的意思很简单,就是判断当前是否正处于夏天(7 - 9月)。

尽管这句代码很短小,但代码表达的意图和代码自身还存在一些距离,阅读代码的人必须要多花一些精力才能明白它传达的意图。

其实可以把这句代码提炼成一个单独的函数,既能更准确地表达代码的意思,函数名本身又能起到注释的作用

let isSummer = function(){
    let date = new Date();
    return date.getMonth() > 6 && date.getMonth() < 10;
};
let getPrice = function( price ){
    if ( isSummer() ){ // 夏天
        return price * 0.5;
    }
    return price;
};

90.png

7. 循环优化



7.1 高效循环

  • 在函数体内,如果有些代码实际上负责的是一些重复性的工作
  • 合理利用循环不仅可以完成同样的功能,还可以使代码量更少
  • 以for循环为例,最常规写法
for (let i = 0; i < arr.length; i++) {
    // do something...
}
  • 大多数人都是这种写法,这种写法的缺点在于,每次循环都要去读取一次数组的长度,性能上并不友好
  • 变量情况的优化写法
for (let i = 0, j = arr.length; i < j; i++) {
    // do something...
}
  • 将长度进行存储,之后循环无需再去读取长度
  • 这只是上面写法的一种变体,另一种写法而已,谈不上优化。因为无块级作用域,所以和上面的效果是一样的
  • 优化版
for (let i = arr.length - 1; i >= 0; i--) {
    // do something...
}

推荐的写法,它在第上面的基础上节约了一个变量100.png

8. 如何提升js性能


8.1 性能至关重要


性能是创建网页或应用程序时最重要的一个方面,特别是加载性能,如果让用户等久了,别人干脆不等了,会造成用户流失

用户对于应用的体验普遍要求提高了(现在来说,2s 内打不开网页的都是不合格的网站)

应用的性能瓶颈,依然是在js上

8.2 优化方向


1. 删除未使用的js代码


未使用的功能性代码以及与之相关的代码(它一样的会编译,运行)

多余的依赖(不需要的及时删除)

2. 数组与对象避免使用构造函数


构造函数是啥?

new Array(), new Object()等

demoObj = () => {
    let obj = new Object()
    obj.name = '朱小明'
    obj.age = 10
    obj.sex = '男'
    return obj
}
  • 推荐写法
demoObj = () => {
    let obj = {
        name: '朱小明',
        age: 10,
        sex: '男'
    }
    return obj
}

3. 避免全局变量


js 的垃圾回收机制是不会销毁全局变量的

所以它会常驻内存

4. 合理使用闭包


闭包可以提供面向对象编程的便利,有私有属性和方法

由于闭包会携带包含它的函数的作用域,因此会比其他函数占用更多的内存

过度使用闭包可能会导致内存占用过多的问题。

所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露

5. 减少循环中的活动


循环本来就耗性能(特别是数据量大的)

方法尽量不要放在循环中执行(执行多次,特别是逻辑复杂的方法,后果可想而知)



目录
相关文章
|
安全 程序员 C++
代码规范:函数设计
除非告诉人们“危险”是什么,否则这个警告牌难以起到积极有效的作用。难以理解的断言常常被程序员忽略,甚至被删除。 ↩︎
96 0
|
2月前
|
程序员 测试技术
程序员的代码规范需求
程序员的代码规范需求
49 1
|
3月前
|
移动开发 前端开发 JavaScript
前端代码规范
前端开发工具组件的广泛应用提升了开发效率,但也带来了代码管理和维护的挑战。为解决这一问题,各团队制定了相应的代码规范。良好的代码规范不仅提升个人代码质量,还便于团队协作。本文从命名、HTML、CSS、JavaScript等方面详细介绍了前端代码规范,强调简洁、有条理、易读的重要性。遵循这些规范,有助于提高开发效率和代码质量。
165 0
|
算法 编译器 程序员
代码规范:其它编程经验
【建议 11-3-4】当心数据类型转换发生错误。尽量使用显式的数据类型转换(让人们知道发生了什么事),避免让编译器轻悄悄地进行隐式的数据类型转换。
67 0
|
安全 编译器 C语言
代码规范:C++函数的高级特性
一个好的编译器将会根据函数的定义体,自动地取消不值得的内联(这进一步说明了 inline 不应该出现在函数的声明中)。
68 0
|
前端开发 算法 JavaScript
前端代码规范与最佳实践
前端代码规范与最佳实践
610 0
|
移动开发 前端开发 JavaScript
前端编码规范
前端编码规范
704 0
|
移动开发 前端开发 JavaScript
|
开发者
代码规范|学习笔记
快速学习 代码规范
156 0
下一篇
DataWorks