JavaScript高级程序设计第四版--第二十八章--最佳实践

可维护性

容易理解

符合常识

容易适配

容易扩展

容易调试

编码规范

可读性

函数和方法

每个函数和方法都应该有注释来描述其用途

大型代码块

多行代码但用于完成单一任务的,应该在前面给出注释

复杂的算法

独特方法解决问题要通过注释解释

使用黑科技

由于浏览器之间的差异,js代码通常包含一些黑科技,需通过注释说明

变量和函数命名

变量名应该是名词

函数名应该是以动词开始

对变量和函数都使用符合逻辑的名称,不必担心长度(处理和压缩解决)

变量和函数以小写字母开头,使用小驼峰形式

类名首字母大写

常量名全部大写以下划线相接

名称尽量使用描述性和直观的词汇,但不要过长

变量类型透明化

初始化

定义变量时,直接对变量赋初值明确其类型

let count = 1; // 明确count为数值型

匈牙利表示法

在变量名前加一个或多个字母,用于表示其类型,o对象、s字符串、i整数、f浮点数、b布尔

let iCount; // 整数
缺点

代码可读性下降、不够直观、并破坏了句子的自然阅读流畅性

类型注释

类型注释放在变量名后面、初始化表达式的前面

let count	/*:int*/	 = 10;
缺点

不能再使用多行注释

/*
	let count	/*:int*/	 = 10;
	let countq1	/*:int*/	 = 10;
*/

松散耦合

HTML/JavaScript

理想情况下,HTML和js应该完全分开,通过外部文件引入js,然后使用DOM添加行为

CSS/JavaScript

通过修改元素的CSS类名,可以把大部分样式限制在CSS文件里。js只负责修改应用样式的类名,而不是影响元素的样式

应用程序逻辑/事件处理程序

应用程序逻辑与事件处理程序分离,不要在事件处理函数里面做逻辑处理,应该将逻辑处理封装成一个函数去调用

案例

function handleKeyPress(event){
    if(event.keyCode == 13){
        let target = event.target;
        let value = 5 * parseInt(target.value);
        if(value > 10){
            document.getElementById("error-msg").style.display = "block";
        }
    }
}

上例应分离为

function validateValue(value){
    let value = 5 * parseInt(value);
        if(value > 10){
            document.getElementById("error-msg").style.display = "block";
        }
}



function handleKeyPress(event){
    if(event.keyCode == 13){
        let target = event.target;
        validateValue(target.value)
        
    }
}

编码惯例

尊重对象所有权

不要修改不属于你的对象,如果你不负责创建和维护某个对象及其构造函数或方法,就不应该对其进行任何修改

不要给实例或原型添加属性、方法

不要重定义已有的

不声明全局变量

尽可能不声明全局变量和函数, 最多创建全局变量,作为其它对象和函数的命名空间

不要比较null

不要用null去做比较,或者不仅仅只用null去比较还要检查变量的类型

使用常量

将常量从应用程逻辑中分离

作用域意识

随着作用域链中作用域数量的增加,访问当前作用域外部变量所需的时间会增加。访问全局变量始终比访问局部变量慢,必须遍历作用域链。任何时候可以缩短作用域链时间的举措都能提升代码性能

避免全局查找

不要使用with语句

with语句会创建自己的作用域,因此会增加代码的作用域链,使用局部变量也可以实现同样的效果

选择正确的方法

避免不必要的属性查找

使用变量和数组相比访问对象属性效率更高

优化循环

简化终止条件

简化循环体

使用后测循环

do-while就是后测循环,避免对终止条件初始化评估,因此更快

展开循环

如果循环次数有限,通常抛弃循环而直接多次调用更快

达夫设备

以八次调用为循环体进行循环,适用不能预知循环次数的情况

let iterations = Math.floor(values.length / 8);
let leftover = values.length % 8;
let i = 0;
if(leftover > 0){
    do{
        process(values[i++]);
    } while(--leftover > 0)
}
do{
    process(values[i++]);
    process(values[i++]);
    process(values[i++]);
    process(values[i++]);
    process(values[i++]);
    process(values[i++]);
    process(values[i++]);
    process(values[i++]);
}while(--iterations > 0);

避免重复解释

eval("console.log(' Hello ')");
let hi = new Function("consoe.log('Hello')");
setTimeout("console.log('Hello')",500);

以上代码都会在运行时,启动新的解释器实例来解析字符串中的代码,解释器实例的创建比较浪费时间

其它性能优化注意事项

原生方法很快

switch比复杂if快

位操作快

语句最小化

多变量声明

一条语句声明多个变量比多条语句声明的执行速度更快

组合迭代性值

任何时候只要使用迭代性值(递增递减),都要尽使用组合语句

数组对象字面量

应尽可能使用数组和对象的字面量,以消除不必要的语句

优化DOM交互

最小化更新

尽量使用文档片段来预先构建DOM文档先不挂载到DOM树,最后再把构建的DOM挂载到DOM树

大量更新innerHTML更快

对于大量的DOM更新,使用innnerHTML要比使用js标准DOM方法创建同样的结构快很多

innerHTML会调用原生DOM而不是js标准DOM方法

缺点

会暴露巨大的XSS攻击面,无论何时使用它填充不受控的数据,都有可能被攻击者注入可执行代码

减少DOM操作

无论是对DOM的属性还是方法的操作,都会触发查询文档,而这个查询文档相当耗时

必要时,声明变量保存中间DOM对象,减少查询范围

构建流程

文件结构

要遵循面向对象编程语言的典型模式,把对象和自定义类保存到自己独立的文件中

注意

把代码分散到多个文件是冲可维护性而不是部署角度出发

对于部署应该把所有源文件合并为一个或多个汇总文件

任务运行器

完成代码检查、打包、转译、启动本地服务器、部署,以及其它可以脚本化的任务

摇树优化

分析出选择性导入的代码,其余模块文件中的代码可以在最终打包得到的文件中完全忽略

模块打包器

识别出js依赖关系,将它们组成一个大文件,完成对模块的拼接,然后生成最终提供给浏览器的输出文件(webpack)

验证

发现js代码中的语法错误和常见的编码错误(ESLint)

压缩

代码大小:浏览器需要解析的字节数

传输负载:服务器实际发送给浏览器的字节数

代码压缩

js压缩工具可以把源代码文件中没用的额外信息和格式删除缩短标识符,并在保证逻辑不变的前提下缩小文件的大小。不保留语法结构

代码最小化

文件变小,代码语法语义存在

JavaScritp编译

把源代码转换为一种逻辑相同但字节更少的形式,编译后代码结构可能不同,但任然具备原始代码相同的行为

JavaScritp转译

转译可以将现代代码转换成更早的ECMAScript版本

目标语言与源语言是一种语言,只是不同级别的抽象(babel.js)

HTTP压缩

大多数Web服务器都具备HTTP压缩

当前所有主流的浏览器都支持客户端解压

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值