最近阅读了《编写可维护的 JavaScript》,在这里记录一下读书笔记。书中主要基于三个方向来说解怎么增长代码的可维护性:编程风格、编程实践、自动化。javascript
笔记已加入到个人博客里,欢迎 Star。html
缩进方式java
使用制表符(Tab 键)。git
命名方式github
变量名用名词。编程
函数名用动词开头数组
null 对象的用法浏览器
// 好的写法 var person = null; function getPerson(num){ if (num >5) { return new Person('Lily'); } else { // 好的写法 return null; } } var person = new Person(); // 好的写法 console.log(person === null);
var person; // 很差的写法 console.log(person === null); function doSomeThing(arr1, arr2){ // 很差的写法 if(arr1 === null){ console.log('arr1 参数没有传递'); } }
使用注释的通常原则是:让代码变得更清晰。咱们通常经过这几点来注释代码:服务器
注释的书写规范:dom
能够加一些注释声明。
var person = null; if (condition) { // 作一些事情 doSomeThing(); // 作一些事情 } /* * 这是建立一个对象 * 第二行 */ var p = new Person(); /** @method merge @param {Object} 被合并的对象 @return {Object} 一个新的对象 **/ function doSomeThing(obj) { return Object.assign(obj,{asd:123}); } // REVIEW: 有更好的写法吗? if(document.all){ }
在语句和表达式一章,书中主要是写关于大括号对齐方式等,如下两点让我影响特别深入:
hasOwnProperty
。定义变量
提示
String 类型能够调用 String 包装器的方法,是由于语句的背后,JS 引擎建立了 String 类型的新实例,紧跟着就销毁了,因此给 String 类型上添加属性和方法是没有用的。
在 WEB 开发中,用户界面是由三个彼此隔离又相互做用的层定义的:HTML、CSS、JavaScript。因为这三个部分是相互做用的,应该尽可能分开这几个模块,以加强代码的可维护性。
将 JS 从 CSS 中抽离出来。
将 CSS 从 JS 中抽离出来。
将 JS 从 HTML 中抽离出来。
<div onclick="xxx"></div>
将 HTML 从 JS 中抽离出来。
div.innerHTML = '<h1>你好</h1>';
JS 可使用一下几种方式来操做 HTML:
咱们都知道,在全局做用域下定义的变量和方法,都会挂载到 window 对象上,随着对象越挂越多,项目也就愈来愈难以维护了。建立全局变量还会致使如下几个问题:
代码脆弱性
难以测试
单全局变量
引用命名空间概念:
AMD 模块化
// AMD 模块定义 define('module-name',['dep1','dep2'],function(dep1,dep2){});
RequireJS 增长了另外一个全局函数 require(),专门用来加载指定的依赖和执行回调函数。
require(['my-book'], function(books){ console.log(books); });
零全局变量
在编写事件处理程序时,咱们应该遵照一下几点:
实际应用场景是这样的:
<button onclick="doSomeThing()">click me</button> <script> // 事件处理程序 function doSomeThing(e) { var clientX = e.clientX; // 不要将e 传入应用逻辑中,只传递须要使用的字段 log(clientX); } // 应用逻辑 function log(text){ console.log(text); } </script>
推荐使用 typeof 来检测原始类型的值。typeof 自己是一个表达式,因此推荐使用无括号的写法。
JS 检测自定义类时,最好的作法是使用 instanceof,这也是惟一的方法。
function Person(){} var p = new Person(): console.log(p instanceof Person);
instanceof 也能够检测引用对象的值。但可能会检测到原型对象上。
var now = new Date(); console.log(now instanceof Date); // true console.log(now instanceof Object); // true
typeof 是检测 JS 检测函数的最佳选择。但 IE8 及其之前的浏览器对 DOM 上的方法实现方式有问题。
// IE 8 会存在问题 typeof document.getElementById // object
使用 Object.prototype.toString.call(value) === '[object Array]' 检测数组效果很不错,在 ES6 中能够经过 Array.isArray 来实现。
检测属性使用如下两个操做符:
在实际的项目中能够遇到这种问题,原本只须要更改一些静态数据,但因为不当心改到了其余业务代码,致使部分业务代码报错。因此,把须要配置的静态数据抽离出来是很是利于维护的。通常按照如下几点将数据抽离出来:
咱们能够将抽离出来的配置数据放在如下几个地方:
咱们在开发项目时,遇到错误其实并不可怕,可怕的将这些错误带到线上环境中去。为此,在程序的一些关键地方,使用自定义错误,可让咱们在上线前提早发现问题,避免出错的影响变大。编写自定义错误能够遵照一下几点:
function MyError(message){ this.message = message; } MyError.prototype = new Error();
在咱们编写代码的时候,会用到不少其余对象,一些是存在于上下文做用域中、一些是存在于其余库里等等,这些对象都不是咱们本身定义的。对于这些对象,咱们要作到彻底不去改动。其余对象主要包括:
即便是目前项目中的对象,只要不是你写的,也不该该随便修改。
不新增方法
若是是必需要修改其余对象,能够经过继承的方式来克隆一个以前的对象,而后再进行扩展。
Polyfills 的优势是:若是浏览器提供原生实现,能够很是轻松的移除他们。若是浏览器没有实现,就使用现有的方法,巧妙地实现,实现过程可能会不精确。
一、user-agent 方式(能够被篡改)。
二、使用特性检测。为特定浏览器的特性进行测试,并仅当特性存在时便可应用特性检测。例如:
// 早期浏览器不支持 getElementById if(document.getElementById){ var dom = document.getElementById('xx') } else if(document.all){ var dom = document.all('xx') }
特性检测的流程:
推断是假设并不是事实。例如:这里根据 getElementsByTagName 去推断 getElementById,显然是不合理的。
if(document.getElementsByTagName){ var dom = document.getElementById('xx') }
经过 document.all 判断就是 IE 浏览器了,这是“自做聪明”的,由于其余浏览器也可能存在 document.all。
if(document.all){ console.log('This is IE'); }
如下列举了书中介绍的自动化配置过程,很实用,如今的项目均可以使用这些思想来配置持续集成。惋惜的是,如今看来书中的信息比较滞后(由于写的早),不少介绍的库已通过时了,这里就不详细介绍了。
自动化测试
组装到一块儿
这本书看着很快,三天时间就看完了,但书中的编码规范,编程实践部分仍是学到了很多东西。如今写代码会经常冒出几个问题:注释该怎么写?类型判断要怎么才最好?数据代码是否抽离?