《编写可保护的 JavaScript》读书笔记

近来阅读了《编写可保护的 JavaScript》,在这里纪录一下读书笔记。书中重要基于三个方向来解说怎样增添代码的可保护性:编程作风编程实践自动化

笔记已加入到我的博客里,迎接 Star。

编程作风

  • 缩进体式格局

    • 运用空格(引荐)。
    • 运用制表符(Tab 键)。

      • 差别的操纵系统关于制表符的诠释不一致,致使看起来不一致。
  • 定名体式格局

    • 变量名用名词。

      • 常量运用大写单词加下划线 MAX_NUM。
    • 函数名用动词开首

      • 组织函数用大驼峰写法。
  • 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 参数没有通报');
  }
}

编写解释

运用解释的平常原则是:让代码变得更清楚。我们平常经由历程这几点来解释代码:

  • 难以明白的代码。
  • 能够被误会的代码。
  • 浏览器 hack。

解释的誊写范例:

  • 解释的上方需要一个空行。
  • 单行解释,假如在尾部解释,需要加一个空格。
  • 多行解释中的每一行需对齐,最好也有一个星号。
  • 能够加一些解释声明。

    • TODO 代码未完成。
    • HACK 代码走了一个捷径,应说明缘由
    • FIXME 代码有题目,应尽快修复
    • REVIEW 代码的修正需要评审
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){

}

语句和表达式

在语句和表达式一章,书中重假如写关于大括号对齐体式格局等,以下两点让我影响迥殊深入:

  • 轮回中只管防备运用 continue,运用条件揣摸替换(可读性更好)。
  • for in 轮回只是用来遍历对象的,不要用来遍历数组。假如不需要遍历原型链上的对象,能够运用 hasOwnProperty

变量、函数和运算符

  • 定义变量

    • 兼并 var 语句,让代码更短。
    • 函数内部的变量定义应作为函数内的第一条语句。
    • for 语句初始化部份不该该有变量声明,应提前到表面。
  • 马上实行的函数需要被一眼看出来,能够将函数用一堆圆括号包裹起来。
  • 严厉情势不要加在全局,只应加在需要用到的函数作用域内,防备影响其他库。
  • 制止运用 eval,new Function,setTimeOut,setInterval 的字符串情势。
  • 三元运算符仅仅用在赋值语句上,不要成为 if else 的替换品。

提醒

String 范例能够挪用 String 包装器的要领,是由于语句的背地,JS 引擎建立了 String 范例的新实例,紧跟着就销毁了,所以给 String 范例上增加属性和要领是没有用的。

编程实践

在 WEB 开辟中,用户界面是由三个相互断绝又相互作用的层定义的:HTML、CSS、JavaScript。由于这三个部份是相互作用的,应当只管离开这几个模块,以加强代码的可保护性。

  • 将 JS 从 CSS 中抽离出来。

    • 防备运用 CSS 表达式。
  • 将 CSS 从 JS 中抽离出来。

    • 防备运用 JS 直接操纵 dom.style 属性。
    • 应当只需要操纵 CSS 的 className 属性。
  • 将 JS 从 HTML 中抽离出来。

    • 防备运用 DOM0 级事宜处置惩罚函数。 比方:<div onclick="xxx"></div>
    • 运用自定义事宜处置惩罚函数。
  • 将 HTML 从 JS 中抽离出来。

    • 防备 JS 运用写死的 HTML 字符串,去 innerHTML 插进去代码。
div.innerHTML = '<h1>你好</h1>';

JS 能够运用一下几种体式格局来操纵 HTML:

  • 要求服务器,返回一段 HTML 文本,然后 innerHTML。
  • 简朴客户端模板,写一个页面不可见的模板,用变量的值去添补模板后,插进去到页面中来。
  • 庞杂客户端模板,运用 Handlebars,建立模板,衬着数据。

防备建立全局变量

我们都晓得,在全局作用域下定义的变量和要领,都邑挂载到 window 对象上,跟着对象越挂越多,项目也就愈来愈难以保护了。建立全局变量还会致使以下几个题目:

  • 定名争执
  • 代码脆弱性

    • 假如大批函数都援用了全局变量,而一旦某个处所不小心改变了值,一切运用的处所就完了。
  • 难以测试

    • 开辟环境,测试环境,线上环境,都需要引入一套差别的全局变量,不方便保护。

处理全局变量计划

  • 单全局变量

    • 只运用一个对象定义在全局变量上,其他的对象都作为这个对象的属性和要领。
    • 援用定名空间概念:

      • 挪用 namespace() 来声明开辟者将要运用的定名空间,即:将对象挂载到哪一个对象下,假如不存在,就建立一个对象。
  • AMD 模块化

    • 定义一个 define 要领,将模块名,依靠,都传进去,在工场要领里就可以运用所依靠的模块了。
// AMD 模块定义
define('module-name',['dep1','dep2'],function(dep1,dep2){});
  • 运用 RequireJS 更好地引入模块。

RequireJS 增添了另一个全局函数 require(),特地用来加载指定的依靠和实行回调函数。

require(['my-book'], function(books){
  console.log(books);
});
  • 零全局变量

    • 假如你的剧本异常短,而且不需要和其他代码发生交互,能够运用一个自实行函数来完成模块化

事宜处置惩罚

在编写事宜处置惩罚顺序时,我们应当恪守一下几点:

  • 断绝运用逻辑。将运用逻辑从一切的事宜处置惩罚顺序中抽离出来。
  • 不要分发事宜对象。只通报需要的数据,给运用逻辑就好了。
  • 让事宜处置惩罚顺序成为接触到 Event 对象的唯一函数。其他需要用到的,就从事宜处置惩罚顺序中通报。

现实运用场景是如许的:


<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 来完成。

检测属性

检测属性运用以下两个操纵符:

  • in 运算符(会检测原型链上的属性)
  • hasOwnProperty

将设置数据从代码中分离出来

在现实的项目中能够碰到这类题目,原本只需要变动一些静态数据,但由于不小心改到了其他营业代码,致使部份营业代码报错。所以,把需要设置的静态数据抽离出来是异常利于保护的。平常依据以下几点将数据抽离出来:

  • URL
  • 展现给用户的字符串
  • 反复的值
  • 设置信息
  • 任何能够发生变动的值

我们能够将抽离出来的设置数据放在以下几个处所:

  • 抽离数据到一个 JSON 文件中。(经由历程要求去猎取)
  • 抽离封装到一个 JSONP 文件中。(经由历程 script 标签猎取)
  • 运用纯 javascript。(直接读取)

抛出自定义毛病

我们在开辟项目时,碰到毛病实在并不恐怖,恐怖的将这些毛病带到线上环境中去。为此,在顺序的一些症结处所,运用自定义毛病,能够让我们在上线条件前发现题目,防备失足的影响变大。编写自定义毛病能够恪守一下几点:

  • 总是在毛病信息中包含函数称号,以及函数失利的缘由。
  • 只在该抛出毛病的处所抛出毛病,不必要过分的举行毛病预判,抛出毛病。
  • 假如运用 try catch ,catch 里不能为空,应当对毛病做一些处置惩罚。
  • 关于自定义毛病,最好是继续 Error 毛病范例,浏览器会给 Error 对象附加一些分外的信息。
function MyError(message){
  this.message = message;
}
MyError.prototype = new Error();

不是你的对象不要动

在我们编写代码的时刻,会用到许多其他对象,一些是存在于上下文作用域中、一些是存在于其他库里等等,这些对象都不是我们本身定义的。关于这些对象,我们要做到完整不去修正。其他对象重要包含:

  • JS 原生对象
  • DOM 对象
  • 浏览器对象模子,BOM 对象
  • 类库的对象

即使是如今项目中的对象,只需不是你写的,也不该该随意修正。

  • 不要掩盖要领
  • 不新增要领

    • 比方:Prototype 库,是在源生 JS 上扩大一些要领,但扩大的要领能够今后被新的范例所运用,Prototype 库不能不马上修正以支撑新的范例。
  • 不删除要领

假如是必需要修正其他对象,能够经由历程继续的体式格局来克隆一个之前的对象,然后再举行扩大。

  • 基于对象的继续(通例的继续)
  • 基于范例的继续(如继续 Error 范例)

关于 Polyfill

Polyfills 的长处是:假如浏览器供应原生完成,能够异常轻松的移除他们。假如浏览器没有完成,就运用现有的要领,奇妙地完成,完成历程能够会不精确。

为了防备对象修正

  • 防备扩大 Object.preventExtensions() 不可扩大
  • 密封对象 Object.seal() 不能删除已存在属性,不可扩大
  • 凝结对象 Object.freeze() 不能修正已存在的属性,不能删除已存在属性,不可扩大

浏览器嗅探

1、user-agent 体式格局(能够被改动)。

2、运用特征检测。为特定浏览器的特征举行测试,并仅当特征存在时即可运用特征检测。比方:

// 初期浏览器不支撑 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');
}

自动化

以下列举了书中引见的自动化设置历程,很有用,如今的项目都能够运用这些思想来设置延续集成。惋惜的是,如今看来书中的信息比较滞后(由于写的早),许多引见的库已过期了,这里就不细致引见了。

  • ant 构建东西
  • 校验语法毛病
  • 文件兼并和加工
  • 文件精简和紧缩
  • 文档化
  • 自动化测试

    • PhantomJS
  • 组装到一同

    • jekins

总结

这本书看着很快,三天时候就看完了,但书中的编码范例,编程实践部份照样学到了不少东西。如今写代码会经常冒出几个题目:解释该怎样写?范例揣摸要怎样才最好?数据代码是不是抽离?

    原文作者:yhlben
    原文地址: https://segmentfault.com/a/1190000018660973
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞