《JS高级程序设计》读书笔记10

最佳实践

可维护性

什么是可维护的代码

  • 可理解性
  • 直观性
  • 可适应性
  • 可扩展性
  • 可调试性

代码约定

一种让代码变得可维护的简单途径是形成一套 JavaScript 代码的书写约定。

可读性

  • 缩进,常见为 4 个空格。
  • 注释,需要进行注释的地方有:
    • 函数和方法
    • 大段代码
    • 复杂的算法
    • Hack

变量和函数命名

  • 变量应为名词
  • 函数名应以动词开始,返回布尔值类型的函数一般以 is 开头
  • 变量和函数都应该使用合乎逻辑的名字,不要担心长度。

变量类型透明

  • 变量初始化
  • 匈牙利标记法,如 bFound(布尔值)、iCount(整数)等
  • 用类型注释,如var found /* Boolean */ = false;

松散耦合

  • 解耦 HTML/JavaScript,尽量不使用内联<script>或者用 HTML 属性分配事件处理程序,尽量不用 JavaScript 直接创建大量 HTML 内容。
  • 解耦 CSS/JavaScript,避免直接操作元素的style属性,最好使用修改className的方式。
  • 解耦应用逻辑/事件处理程序。

编程实践

尊重对象所有权

如果你不负责维护某个对象、它的对象或者它的方法,那么你就不能对他们进行修改。

  • 不要为实例或原型添加属性;
  • 不要为实例或原型添加方法;
  • 不要重定义已存在的方法。

最佳的方法是永远不修改不是由你所有的对象,可以通过以下方式为对象创建新的功能:

  • 创建包含所需功能的新对象,并用它与相关对象进行交互。
  • 创建自定义类型,继承需要进行修改的类型。然后为自定义类添加额外功能。

避免全局变量

使用命名空间,如:

避免与 null 进行比较

  • 如果值为一个引用类型,使用instanceof操作符检查其构造函数;
  • 如果值为一个基本类型,使用typeof检查其类型
  • 如果是希望对象包含某个特定的方法名,则使用typeof操作符确保指定名字的方法存在于对象上。
  • 代码中的null比较少,就容易确定代码的目的,并消除不必要的错误。

使用常量

关键在于将数据和使用它的逻辑进行分离,要注意的值的类型如下:

  • 重复值:多处用到的值。
  • 用户界面字符串:任何用于显示给用户的字符串,都应该被抽取出来以方便国际化。
  • URLs:在 Web 应用中,资源位置很容易变更,推荐使用一个公用的地方存放所有的 URL。
  • 任意可能会更改的值。

性能

注意作用域

随着作用域链中的作用域数量的增加,访问当前作用域意外的变量的时间也在增加。访问全局变量的速度比访问局部变量慢啊,因为要遍历作用域链。

避免全局查找

全局查找的开销比直接使用局部变量的开销要大,要在函数中多把全局变量存储为局部变量。

避免 with 语句

with语句会创建自己的作用域,会增加作用域链长度,会导致执行代码速度变慢。

选择正确方法

避免不必要的属性查找

尽可能多地使用局部变量将属性查找替换为值查找。

优化循环

  • 减值迭代,从最大值开始迭代。
  • 简化终止条件,每次循环过程都会计算终止条件,所以必须保证它尽可能快。
  • 简化循环体
  • 使用后测试循环

展开循环

  • 当循环的次数是确定的,消除循环并使用多次函数调用往往更快。
  • 循环次数不一定,使用 Duff 装置处理循环。

避免双重解释

当 JavaScript 代码想解析 JavaScript 的时候就会存在双重解释惩罚。这种情况要尽量避免出现。

性能的其他注意事项

  • 原生方法较快
  • switch语句较快
  • 位运算符较快

最小化语句数

完成多个操作的单个语句要比完成单个操作的多个语句快。

  • 多个变量声明变成使用逗号分隔的一句变量声明。
  • 插入迭代值
  • 使用数组和对象字面量

优化 DOM 交互

  • 最小化现场更新,使用document.createDocumentFragment()更新节点。
  • 使用innerHTML,使用它要比 DOM 方法快。
  • 使用事件***,可以避免为每个节点都绑定事件处理程序
  • 注意 HTMLCollection,访问它都会在文档进行查询,开销很小,需要减少它的访问次数。发生以下情况会返回 HTMLCollection 对象:
    • getElementsByTagName();
    • 获取元素的childNodes属性;
    • 获取元素的attributes属性;
    • 访问了特殊的集合,document.forms、document.images等。

部署

构建过程

前端的代码不应该原封不动的放在浏览器中,理由如下:

  • 知识产权问题
  • 文件大小
  • 代码组织

可以用 Ant 构建。

验证

主要使用 JSLint,现在要使用 ESLint。

压缩

  • 文件压缩,一般会删除额外的空白和注释,缩短变量名。
  • HTTP 压缩,一般由浏览器进行。

Chapter25. 新兴的 API

动画

早期动画循环

使用setInterval()方法控制所有动画,不过定时器并不能保证动画按时执行。

平滑动画的最佳循环间隔是 1000ms/60,即 17ms。

循环间隔的问题

浏览器的计时精度并不是到毫秒级的,也会对动画实际效果有影响。

requestAnimationFrame()

使用如下方式保证requestAnimationFrame()的兼容性。这个方法用于告诉浏览器某些 JavaScript 代码要执行动画。解决了浏览器不知道 JavaScript 动画什么时候开始、不知道最佳循环间隔和不知道代码什么时候执行的问题。

Page Visibility API

该 API 是为了让开发人员知道页面是否对用户可见而推出的。这个 API 本身非常简单,由以下几部分组成:

  • document.hidden:表示页面是否隐藏,包括在后台标签页中或者浏览器最小化。
  • document.visibilityState:表示下列 4 个可能的状态值。
    • 页面在后台标签页或浏览器最小化
    • 页面在前台标签页中。
    • 实际的页面已经隐藏,但用户可以看到页面的预览。
    • 页面在屏幕外执行预渲染处理。
  • visibilitychange事件:当文档从可见变为不可见或从不可见变为可见时,触发该事件。

Geolocation API

地理定位的实现是navigator.geoloaction 对象,这个对象包含 3 个方法。

第一个方法是getCurrentPosition(),调用这个方法就会触发请求用户共享地理定位信息的对话框。这个方法接收 3 个参数:成功回调函数、可选的失败回调函数和可选的选项对象。

其中,成功回调函数会接受到一个 Position 对象参数,有两个属性coords和timestamp。

coords可能包含如下信息:

  • latitude:以十进制数表示的纬度。
  • longtitude:以十进制数表示的经度。
  • accuracy:经纬度坐标精度,以米为单位。
  • altitude:以米为单位的还不高度,如果没有相关数据则为null。
  • alitudeAccracy:海拔高度的精度,以米为单位。
  • heading:指南针的方向,0 度表示正北,值为 NaN 表示没有检测到数据。
  • speed:速度,即每秒移动多少米,没有则为null。

第二个参数即失败回调函数,在被调用的时候也会接收到一个参数,这个参数包含两个属性:message和code。

第三个参数是一个配置选项对象,用于设定信息的类型。可以设置的选项有三个:

  • enableHighAccuracy:表示必须尽可能使用最准确的位置信息。
  • timeout:表示等待位置欣欣的最长时间。ma
  • maximumAge表示上一次取得的坐标信息的有效时间。

如果希望跟踪用户的位置,可以用watchPosition()方法,参数与getCurrentPostion()相同。调用该方***返回一个数值标识符,可以用于传入clearWatch()方法取消监控操作。

File API

File API 在表单中的文件传入字段的基础上,又添加了一些直接访问文件信息的接口。HTML5 在 DOM 中为文件输入元素添加了一个files集合。每个 File 对象都有下列属性:

  • name:本地文件系统中的文件名
  • size:文件的字节大小。
  • type:字符串,文件的 MIME 类型。
  • lastModifiedData:字符串,文件上一次被修改的时间。

FileReader 类型

通过 FileReader 类型可以读取文件中数据,是一种异步文件读取机制,可以想象成 XMLHttpRequest。提供以下几个方法:

  • readAsText(file, encoding):以纯文本形式读取文件,将读取到的文本保存在result属性中。第二个参数用于指定编码类型(可选的)。
  • readAsDataURL(file):读取文件并将文件以数据 URI 的形式保存在result属性中。
  • readAsBinaryString(file):读取文件并将一个字符串保存在result属性中,字符串中的每个字符表示一字节。
  • readAsArrayBuffer(file):读取文件并将一个包含文件内容的 ArrayBuffer 保存在result属性中。

由于读取过程是异步的,因此 FileReader 也提供了几个事件,比较实用的是progress、error、load这三个事件。下面是使用上述三个事件的例子:

要中断读取过程,可以调用abort()方法,会触发abort事件。在触发load、error或abort事件后,会触发loadend事件。

读取部分内容

File 对象还支持一个slice()方法,该方法接受两个参数:起始字节和要读取的字节数。会返回一个 Blob 实例,Blob 是 File 类型的父类型。下面是一个通用函数:

Blob 类型有一个size属性和type属性。下例只读取文件的 32B 内容。

对象 URL

也称为 blob URL,指的是引用保存在 File 或 Blob 数据中的 URL。使用它的好处是可以不必把文件内容读取到 JavaScript 中而直接使用文件内容。创建 URL 对象,可以使用window.URL.createObjectURL()方法,并传入 File 或 Blob 对象。通用函数:

该函数的返回值是一个字符串,指向一块内存地址。因为这个字符串是 URL,所以在 DOM 中也能使用。如下,可以显示图像文件:

直接把对象 URL 放在<img>标签中,省去了在 JavaScript 中读数据的麻烦。<img>会找到相应内存地址,直接读取数据并将图像显示在页面中。

如果不需要相应数据,可以用window.URL.revokeObjectURL()释放内存。

读取拖放的文件

通过drop的event对象的event.dataTransfer.files属性,可以读取被放置的文件。代码如下:

Web 计时

核心是window.performance对象。页面的所有度量信息,都包含在这个对象里面。Web Timing 规范一开始就为performance对象定义了两个属性:

  • redirectCount:页面加载前的重定向次数。
  • type:数值常量,表示刚刚发生的导航类型。
    • performance.navigation.TYPE_NAVIGATE(0):页面第一次加载。
    • performance.navigation.TYPE_RELOAD(1):页面重载过。
    • performance.navigation.TYPE_BACK_FORWARD(2):页面是通过“后退”或“前进”按钮打开的。

另外,performance.timing属性也是一个对象,但这个对象的属性都是时间戳,不同事件会产生不同的值。如下:

  • navigationStart
  • unloadEventStart
  • unloadEventEnd
  • redirectStart
  • redirectEnd
  • fetchStart
  • domainLookupStart
  • domainLookupEnd
  • connectStart
  • connectEnd
  • secureConnectStart
  • requestStart
  • responseStart
  • responseEnd
  • domLoading
  • domInteractive
  • domContentLoadedEventStart
  • domContentLoadedEventEnd
  • domComplete
  • loadEventStart
  • loadEventEnd

Web Workers

Web Workers 规范通过让 JavaScript 在后台运行解决了单线程的缺点,不会影响用户体验。

使用 Worker

实例化 Worker 对象并传入要执行的 JavaScript 文件名就可以创建一个新的 Web Worker。如:

这行代码会导致浏览器下载stufftodo.js,但只有 Worker 接收到消息才会实际执行文件中的代码。要给 Worker 传递消息,可以使用postMessage()方法。与 XDM 不同的是,在所有支持的浏览器中,postMessage()都能接收对象参数。

然后通过message和error事件与页面通信。来自 Worker 的数据保存在event.data中。任何时候,只要调用terminate()方法就可以停止 Worker 的工作。而且,Worker 中的代码会立即停止执行,后续过程都不会再发生。

Worker 全局作用域

Web Worker 中的全局对象是worker对象本身。也就是说,在这个特殊的全局作用域中,this和self引用的都是worker对象。为便于处理数据,Web Worker 本身也是一个最小化的运行环境。

  • 最小化的navigator对象,包括onLine、appName、appVersion、userAgent和platform属性;
  • 只读的location对象;
  • 定时器方法;
  • XMLHttpRequest 构造函数。

在 Worker 内部,调用close()方法也可以停止工作。

包含其他脚本

既然无法在 Worker 中动态创建新的<script>元素,但可以调用importScripts()方法。这个方法接受一个或多个指向 JavaScript 文件的 URL。每个加载过程都是异步进行的,因此所有脚本加载并执行之后,importScripts()才会执行。例如:

#笔记##读书笔记##设计#
全部评论

相关推荐

工作基本定了,比较满意。这深度学习真是难搞啊,论文看不懂,代码看不懂,不会改,创新点???&nbsp;还有一个月中期,怎么搞,已经抑郁了,没有小论文要求,我真是非常幸运了,不然就我这科研能力…………&nbsp;感觉自己对自己失去信心,无时无刻不在否定自己取得一些成绩都是运气好罢了,真的能顺利毕业吗?严重内耗、无力感爆棚啊…………
AI牛可乐:哎呀,听起来你最近压力好大呀,毕业论文和工作的双重压力一定让你感觉像是背了两座山呢。深度学习确实挺复杂的,就像是要在一片迷雾中找到出路一样。但是,你已经很棒了,工作都定好了,这是很大的成就呢! 论文的事情,别太担心。每个人都有看不懂代码和论文的时候,这是正常的。至于创新点嘛,有时候灵感就像小猫一样,需要一点一点地哄出来的。你可以先试试把你看过的资料整理一下,说不定就能找到新的思路呢。 中期答辩前,你可以列个计划,一步一步来,把大问题分解成小问题,一点一点克服。记得,你不是一个人在战斗,你的导师、同学都是你的战友哦。 至于信心嘛,别否定自己,每个人都会有低谷的时候。你已经取得的成绩,都是你实力的体现。毕业不是问题,只要你不放弃,就一定能顺利走过去的。加油哦,我相信你可以的! 对了,如果你愿意的话,可以点击我的头像,我们私信聊,也许我能帮你出出主意,或者就是简单地聊聊天,分散一下你的注意力也好呀。🐮💪🌟
点赞 评论 收藏
分享
点赞 评论 收藏
分享
点赞 收藏 评论
分享
牛客网
牛客企业服务