学习第十四天(2019-11-27)

第二十四章 最佳实践

一、可维护性

    随着JavaScript代码的增多,编写可维护的代码就变得尤为重要。

1、代码约定

   a、命名约定:

       变量名应为名词 carpeople

       函数名以动词开头,如getName()。 返回布尔值则以is-开头,如isEnable()

   b、变量类型透明(便于知道一个变量的类型)

       初始化,在定义一个变量过后,初始化一个值,来暗示他将来应该如何应用。
               var found = false;
       匈牙利标记法,变量名前加一个或多个字符表示数据类型
               o对象 s字符串 i整数 f浮点数 b布尔值,如: var bFound = false;
        类型注释
                var found /*:Boolean*/ = false;

2、松散耦合

      只要应用的某个部分过分依赖于另一部分,代码就是耦合过紧,难于维护。典型的问题如:对象直接引用另一个对象,并且当修改其中一个的同时需要修改另外一个。紧密耦合的软件难于维护并且需要经常重写。 

     以下是要牢记的应用和业务逻辑之间松散耦合的几条原则: 

         a、HTML和JavaScript各自代表解决方案中的不同层次: HTML 是数据, JavaScript 是行为
         b、勿将event对象传给其他方法,只传event对象中所需的数据
         c、任何可以在应用层面的动作都应该可以在不执行任何事件处理程序的情况下进行
         d、任何事件处理程序都应该处理事件,然后将处理权转交给应用逻辑

3、编程实践

   a、尊重对象的所有权:

        在企业环境中最重要的编程实践就是尊重对象所有权,它的意思是你不能修改不属于你的对象。简单地说,如果你不负责创建或维护某个对象、它的对象或者它的方法,那么你就不能对它们进行修改。更具体地说: 不要为实例或原型添加属性;不要为实例或原型添加方法;不要重定义已存在的方法。 

    b、避免使用全局变量

        与尊重对象所有权密切相关的是尽可能避免全局变量和函数。这也关系到创建一个脚本执行的一致的和可维护的环境。多创建一个全局变量,让其他对象和函数存在其中。

 1 //两个全局量——避免!!
 2 var name = "Nicholas";
 3  function sayName(){ alert(name); } 
 4 
 5 //一个全局量——推荐
 6 var MyApplication = {
 7      name: "Nicholas", 
 8      sayName: function(){
 9          alert(this.name);     
10      }
11 }; 
12  

单一的全局量的延伸便是命名空间的概念,命名空间包括创建一个用于放置功能的对象。

命名空间很重要的一部分是确定每个人都同意使用的全局对象的名字,并且尽可能唯一,让其他人不太可能也使用这个名字。在大多数情况下,可以是开发代码的公司的名字,例如YAHOO或者Wrox。

可以如下例所示开始创建命名空间来组合功能:

//创建全局对象
 var Wrox = {}; 
 
//为 Professional JavaScript 创建命名空间
Wrox.ProJS = {}; 
 
//将书中用到的对象附加上去
Wrox.ProJS.EventUtil = { ... };
Wrox.ProJS.CookieUtil = { ... }; 
 

在这个例子中,Wrox是全局量,其他命名空间在此之上创建。如果本书所有代码都放在Wrox.ProJS命名空间,那么其他作者也应把自己的代码添加到Wrox对象中。只要所有人都遵循这个规则,那么就不用担心其他人也创建叫做EventUtil或者CookieUtil 的对象,因为它会存在于不同的命名空间中。

  c、避免与 null 进行比较 

    如果看到了与 null 比较的代码,尝试使用以下技术替换:

       如果值应为一个引用类型,使用 instanceof 操作符检查其构造函数;如果值应为一个基本类型,使用 typeof 检查其类型; 

       如果是希望对象包含某个特定的方法名,则使用 typeof 操作符确保指定名字的方法存在于对象上。

   代码中的 null 比较越少,就越容易确定代码的目的,并消除不必要的错误。  

  d、使用常量

二、性能

   1、注意作用域

  •  避免全局查找
  •  将在一个函数中会用到多次的全局对象存储为局部变量 
 1 // 避免全局查找
 2 function updateUI(){
 3     var imgs = document.getElementsByTagName("img");
 4     for(let i = 0; i < imgs.length; i ++){
 5         imgs[i].title = document.title + "img" + i; // 这里要通过作用域链查找document很多次
 6     }
 7 }
 8 将多次引用的全局变量存储为局部变量
 9 function updateUI(){
10     var doc = document;// 只查找document一次,查到后缓存起来
11     var imgs = document.getelementsByTagName("img");
12     for(let i =0 ; i < img.length; i++){
13         imgs[i].title = doc.title + "img" + i;
14     }
15 }

  2、避免使用with语句

  3、使用变量和数组要比访问对象上的属性更有效率

     对象上的任何属性查找都比访问变量和数组花费更长时间,因为必须在原型链上对拥有该名称的属性进行一次搜索
     一旦多次用到对象属性,就应该将其存储在局部变量中,第一次访问该值是O(n),以后都是O(1)
    尽可能多的使用局部变量将属性查找替换为值查找

  4、优化循环

        减值迭代;简化终止条件(使用值,而非属性查找);简化循环体;使用后测试循环do-while

  5、展开循环与避免双重解释

  6、最小化语句块数

  • 多个变量一起声明
  • 插入迭代值
  • 使用字面量,而不是对象构造函数

  7、优化DOM更新

       a、最小化现场更新:利用documentFragment;使用innerHTML

       b、事件委托(代理)

       c、最小化访问HTMLCollection的次数

三、部署与压缩

   为了协助部署,推荐设置一个可以将JavaScript合并为较少文件(理想情况是一个)的构建过程。
   有了构建过程也可以对源代码自动运行额外的处理和过滤。例如,你可以运行 JavaScript验证器来确保没有语法错误或者是代码没有潜在的问题。在部署前推荐使用压缩器将文件尽可能变小。和HTTP压缩一起使用可以让JavaScript文件尽可能小,因此对整体页面性能的影响也会小。

第二十五章 新兴的API

  随着HTML5的出现,面向未来Web应用的JavaScript API也得到了极大的发展。这些API没有包含在HTML5规范中,而是各自有各自的规范。但是,它们都属于“HTML5相关的 API”。

 一、requestAnimationFrame() 

  requestAnimationFrame():是一个着眼于优化JavaScript动画的API,能够在动画运行期间发出信号。通过这种机制,浏览器就能够自动优化屏幕重绘操作。 

二、Page Visibility

让开发人员知道用户什么时候正在看着页面,而什么时候页面是隐藏的。页面最小化,或隐藏在其他标签后。

  属性:
     document.hidden Boolean
     document.visibilityState —> Chrome(hidden, visible, prerender)
  事件:visibilitychange 事件

三、Geolocation API

   在得到许可的情况下,可以确定用户所在的位置。在移动Web应用中,这个API非常重要而且常用,Geolocation API在浏览器中的实现是navigator.geolocation 对象。 

四、File API

  File API是为Web开发人员提供一种安全的方式,以便在客户端访问用户计算机中的文件,可以读取文件内容,用于显示、处理和上传。与HTML5的拖放功能结合,很容易就能创造出拖放上传功能。 

1、FileReader类型

   实现的是一种异步文件读取机制,包含的方法:

       readAsText(file,encoding):以纯文本形式读取文件,保存到result属性中,第二个参数可选
       readAsDataURL(file):读取文件并将文件以数据URI的形式保存到result属性
       readAsBinaryString(file):读文件并将一个字符保存在result属性,字符串中每个字符表示一字节
       readAsArrayBuffer(file):读文件并将一个包含文件内容的ArrayBuffer保存在result属性中
2、读取部分内容
       File对象支持slice方法
3、对象URI
      对象URL也被称为blob URL,指的是引用保存在File或Blob中数据的URL。使用对象URL的 好处是可以不必把文件内容读取到 JavaScript中而直接使用文件内容。为此,只要在需要文件内容的地方提供对象URL即可。
4、读取拖放文件:event.dataTransfer.files
5、使用XHR上传文件
  通过File API能够访问到文件内容,利用这一点就可以通过XHR直接把文件上传到服务器。当然,把文件内容放到send()方法中,再通过POST请求,的确很容易就能实现上传。但这样做传递的是文件内容,因而服务器端必须收集提交的内容,然后再把它们保存到另一个文件中。其实,更好的做法是以表单提交的方式来上传文件。 这样使用FormData类型就很容易做到了,如下:
 1 var droptarget = document.getElementById("droptarget");
 2 function handleEvent(event){
 3      var info = "",
 4          output = document.getElementById("output"),
 5          data, xhr,
 6          files, i, len; 
 7  
 8     EventUtil.preventDefault(event); 
 9     if (event.type == "drop"){
10          data = new FormData();
11          files = event.dataTransfer.files;
12          i = 0;
13          len = files.length; 
14  
15         while (i < len){
16              data.append("file" + i, files[i]);
17              i++;
18         } 
19  
20         xhr = new XMLHttpRequest();
21         xhr.open("post", "FileAPIExample06Upload.php", true);                 xhr.onreadystatechange = function(){
22              if (xhr.readyState == 4){
23                  alert(xhr.responseText);
24              }
25         };
26         xhr.send(data);
27      }
28 } 
29  
30 EventUtil.addHandler(droptarget, "dragenter", handleEvent);
31 EventUtil.addHandler(droptarget, "dragover", handleEvent); 
32 EventUtil.addHandler(droptarget, "drop", handleEvent); 

   首先,要创建一个FormData 对象,通过它调用 append()方法并传入相应的 File 对象作为参数。然后,再把 FormData 对象传递 给 XHR的 send()方法,结果与通过表单上传一模一样。 

五、Web计时

  页面性能一直都是Web开发人员最关注的领域。但直到最近,度量页面性能指标的唯一方式,就是提高代码复杂程度和巧妙地使用 JavaScript的Date对象。Web Timing API改变了这个局面,让开发人员通过JavaScript就能使用浏览器内部的度量结果,通过直接读取这些信息可以做任何想做的分析。 

六、Web Workers

   可以运行异步 JavaScript 代码,避免阻塞用户界面。

  1. 关于Worker,最重要的是要知道他所执行的JavaScript代码完全在另一个作用域中,与当前网页代码不共享作用域。
  2. Worker中的代码不能访问DOM,也无法更改页面外观。
  3. 比较耗时的操作,转交给Worker就不会阻塞用户界面。

猜你喜欢

转载自www.cnblogs.com/xiaoxb17/p/11945720.html