javaScript高级程序设计(红宝书)之第28章

65 阅读7分钟

一、可维护性

1、什么是可维护
    容易理解:不需要求助原开发者
    符合常识:好理解
    容易适配:数据改变,不需要完全重写
    容易扩展:代码架构设计,后续好扩展
    容易调试:好定位错误
 2、怎么去实践
    1、可读性:函数和方法 注释描述用途,参数含义
           大型代码块:注释
           复杂的算法:注释
            
    2、变量和函数命名 :(避免没有用的变量名)
            变量名--名词
            函数名---动词  如:getPrototypeOf 一些原生方法
            返回布尔值--函数通常is开头 如:原生的方法isNaN
            变量和函数都使用符合逻辑的名称
            变量和函数和方法应该以小写字母开头,使用驼峰形势,类名应该首字母大写,常量值应该全部使 
             用大写字母并以下划线相接
    3、变量类型透明化:通过初始化
                    匈牙利表示法(目前几乎不用)
    4、松散耦合:
             解耦html(数据)/javascript(行为)
             解耦css/javascript
             解耦应用程序逻辑、事件处理程序
     5、编码惯例:
            不修改不属于你的对象,如原生对象,不要给实例或原型添加属性和方法,不重新定义方法,因为
            不是你的对象,可变性很大,有可能会覆盖原有的属性和方法
     6、不声明全局变量:(目前的vue和react基本上都避免全局)
             与尊重对象所有权密切却相关的是尽可能不声明全局变量和函数。
      7、不要比较null: javascript不会自动做任何类型检查,最常见的类型检查时看值是不是null,然而,
                        与null进行比较的代码太多了,其中很多因为类型检查不够而频繁引发错误。
      
function sortArray(values) { 
if (values != null) { 
// 不要这样比较!
values.sort(comparator);
} }


function sortArray(values) {
if (values instanceof Array) { 
// 推荐 
values.sort(comparator); } }

8、使用常量:重复出现的值:任何使用超过一次的值都应该提取到常量中,这样可以消除一个值改了而
                                   另一 个值没改造成的错误。这里也包括 CSS 的类名。
                   
                   用户界面字符串:任何会显示给用户的字符串都应该提取出来,以方便实现国际化。
                   URL:          Web 应用程序中资源的地址经常会发生变化,因此建议把所有 URL 集
                                   中放在一个地 方 管理。
                   任何可能变化的值:任何时候,只要在代码中使用字面值,就问问自己这个值将来是否可
                                    能会 变。如果答案是“是”,那么就应该把它提取到常量中
 

二、性能

 1、作用域意识
          * 避免全局查找,因为作用域链的查找,全局的更加浪费时间
          
function updateUI() { 
let imgs = document.getElementsByTagName("img");
for (let i = 0, len = imgs.length; i < len; i++) {
imgs[i].title = '${document.title} image ${i}';
}
let msg = document.getElementById("msg");
msg.innerHTML = "Update complete."; 
}

//三个地方引用了全局document对象,如再数据多的情况下,document查看的次数就很多,每次都要遍历一次作用域链,改变如下

function updateUI() { 
let doc = document;//只查一次document
let imgs = doc.getElementsByTagName("img"); 
for (let i = 0, len = imgs.length; i < len; i++) { 
imgs[i].title = '${doc.title} image ${i}'; 
} 
let msg = doc.getElementById("msg"); 
msg.innerHTML = "Update complete."; 
}
  • 一个经验规则就是: **只要函数中有引用超过两次的全局对象,就应该把这个对象保存为一个局部变量 **

2、选择正确的方法(重点) * 避免不必要的属性的查找,O表示算法复杂度, 最简单也是最快的算法可以表示为常量值或O(1)。

image.png

  • O(1) ========指字面量 和 保存在变量中的值,访问数据元素也是O(1)操作
  • 对象的复杂度是O(N),访问对象的每个属性都比访问变量或数组花费的时间长, 特别要注意避免通过多次查找获取一个值

O(1) ========指字面量 和 保存在变量中的值,访问数据元素也是O(1)操作====,表示读取常量值所需的时间不会因值得多少而变化。读取常量值是效率极高得操作,因此非常快

let value = 5; 
let sum = 10 + value; 
console.log(sum);
两个的效率是一样的
let values = [5, 10];
let sum = values[0] + values[1];
console.log(sum);

使用变量和数组相比访问对象属性效率更高,对象的复杂度是O(N),访问对象的每个属性都比访问变量或数组花费的时间长,因为查找属性名要搜索原型链,查找的属性越多,执行的时间就会越长

let values = { first: 5, second: 10 }; 
let sum = values.first + values.second; 
console.log(sum);
//这个例子使用两次属性查找来计算 sum 的值。一两次属性查找可能不会有明显的性能问题,但几百 上千次则绝对会

      拖慢执行速度。



//特别要注意避免通过多次查找获取一个值。
let query = window.location.href.substring(window.location.href.indexOf("?"));
//应该如下:
let url = window.location.href; 
let query = url.substring(url.indexOf("?"));

3、循环优化(这个自己还没改过来)

4、其他性能

1、原生方法,(尽可能的使用原生方法,)而不是(用javascript写的方法)为什么呢,因为原生方法是用cc++等编译型语言写的,所有js写的方法要快得多,js中经常被忽略的是Math对象上哪些执行复杂数学运算的
   方法,这些方法总是比执行相同任务的js函数快。
2switch 语句更快
3、位操作很快

5、语句最小化、

 1、多个变量声明
 
// 有四条语句:浪费 
let count = 5;
let color = "blue"; 
let values = [1,2,3]; 
let now = new Date();
优化如下:
// 一条语句更好 
let count = 5, 
color = "blue",
values = [1,2,3],
now = new Date();

2、使用数组和对象字面量
   
/ 创建和初始化数组用了四条语句:浪费
let values = new Array(); 
values[0] = 123; 
values[1] = 456; 
values[2] = 789;


// 创建和初始化对象用了四条语句:浪费
let person = new Object(); 
person.name = "Nicholas"; 
person.age = 29;
person.sayName = function() { console.log(this.name); 
};


如下:
/ 一条语句创建并初始化数组
let values = [123, 456, 789]; 
// 一条语句创建并初始化对象
let person = {
name: "Nicholas",
age: 29, sayName() { 
console.log(this.name); 
} };

三、部署

开发软件的典型的模式是编码,编译,测试即写代码,编译,之后运行。但是js不是编译型语言,所以这个流程会变成编码,测试,但是,我们应该将代码处理之后在进行运行。

1、构建流程 
   文件结构:合适的文件结构
   任务运行器:完成代码检查,打包,转译,启动本地服务器,部署,如:gulp 和grunt主流的任务运行器
   摇树优化: 构建工具能确定代码各部分之间的依赖关系,能确定代码中哪些内容是不需要的
   模块打包器:以模块形式编写代码,但是交付只要少数,就是构建是间模块的js打包在一起,实现打包的工作
              很多:  wepack  rollupt  browserify,可以将基于模块的代码转换为普遍兼容的网页脚本
   
 2、验证:最流行的是 Douglas Crockford 的 JSLint 和 ESLint,编写代码的时候就该开启,在开发过程中
 添加代码检查工具有助于避免出错。推荐开发者在构建流程中也加入代码检查环节, 以便在潜在问题成为错误之
 前识别它们。
 3、压缩:
        代码压缩: 注释、额外的空格、长变量或函数名都能提升开发者的可读性,但对浏览器而言这些都是多
                  余的字 节。压缩工具可以通过如下操作减少代码大小:
                                                           删除空格(包括换行);
                                                           删除注释
                                                           缩短变量名、函数名和其他标识符
         js编译:类似于最小化,JavaScript 代码编译通常指的是把源代码转换为一种逻辑相同但字节更少的
                 形式。 与最小化的不同之处在于,编译后代码的结构可能不同,但仍然具备与原始代码相同
                 的行为。编译器通 过输入全部 JavaScript 代码可以对程序流执行稳健的分析。 编译可能
                 会执行如下操作: 
                               删除未使用的代码;
                               将某些代码转换为更简洁的语法;
                               全局函数调用、常量和变量行内化
         js转译:通过 JavaScript 转译,可以在开发时使用最新的语法特性而不用担心浏览器的兼容性问题
         http压缩:启用 HTTP 压缩可以让网络传输的 JavaScript 文件尽可能小,从而提升页面的整体性能