JavaScript 最佳实践:帮你提升代码质量


Posted in Javascript onDecember 03, 2016

每天学一些新东西可以让一个理性之人走上不凡之路。而作为开发人员,不断的学习新东西则是我们工作的一部分, 不论这些新东西是不是来源于积极的学习经验。

在本篇教程中,我将指出一些重要的 JavaScript 最佳实践,让你不必去用另外一种艰难的方式来了解它们。准备好去升级你的代码吧!

JavaScript 最佳实践:帮你提升代码质量

 1. 避免对全局作用域的污染

声明变量是一件很有趣的事情。有时候即使你不想这样做,但也有可能会定义出全局变量。在如今的浏览器中,全局变量都被存储在 window 对象中。而因为有许多的东西都在那个里面,所以你有可能把一些默认值都给覆盖掉了。

假设你有一个 HTML 文件,里面包含了一个 <script> 标记,而这个标记内含 (或者通过引用一个 JavaScript 文件而加载) 如下内容:

var foo = 42;
console.log(foo);

这段代码很明显会让控制台输出 42。不过因为代码并不是放到一个函数里面去执行的,因此其执行的上下文就会是全局的那个。因此,变量就会被附加到 window 对象上。这就意味着 window.foo 的值也会是 42。

这样是挺危险的,因为你可以把已经存在的全局变量给覆盖掉:

function print () {
  // do something
}
print();

当执行 window.print (或者只是执行 print) 的时候, 它不会打开打印弹窗,因为我们已经将原生的打印弹窗逻辑给覆盖掉了。

解决这个问题的方案相当简单; 我们需要一个会在定义后立即被调用到的闭包函数, 如下所示:

// Declare an anonymous function
(function () {
  var foo = 42;
  console.log(window.foo);
  // → undefined
  console.log(foo);
  // → 42
})();
//^ and call it immediately

或者你也可以选择将 window 以及其它全局的东西(例如 document)都作为参数传给那个函数(这样做也可能对性能会有所提升):

(function (global, doc) {
 global.setTimeout(function () {
   doc.body.innerHTML = "Hello!";
 }, 1000);
})(window, document);

因此你得使用闭包函数来避免创建出什么全局的东西来。注意在这里因为要专注于代码本身,所以我不会在后面的代码片段中使用闭包函数。

提示: browserify 是另外一种避免创建全局变量的方式。它采用了你在 Node.js 同样会用到的 require 函数的方式。

顺便说一下, Node.js 会自动将你的文件封装进函数里面。它们看起来先下面这样:

(function (exports, require, module, __filename, __dirname) {
// ...

因此,如果你认为 require 函数式全局的,好吧,并不是。它无非就是一个函数的参数。

你知道吗?

因为 window 对象包含了所有的全局变量,又因为它自己也是全局的,因此 window 自己内部也引用了它自己:

window.window.window
// => Window {...}

这是一位 window 对象是一个循环引用对象。下面展示了如何创建这样的一个对象:

// Create an object
var foo = {};
// Point a key value to the object itself
foo.bar = foo;
// The `foo` object just became a circular one:
foo.bar.bar.bar.bar
// → foo

或者,为了展示你对 JavaScript 的无限的热爱之情,你可以当回发烧友,代码如下:

JavaScript 最佳实践:帮你提升代码质量

是的,你可以几乎没完没了(也有可能会等到浏览器崩溃)的展开这个对象。

 2. 好的 use strict 使用习惯

要严格使用 use strict! 这无非就是在你的代码中加了一行,给你的脚本增加更多的小把戏。

例如:

// This is bad, since you do create a global without having anyone to tell you
(function () {
   a = 42;
   console.log(a);
   // → 42
})();
console.log(a);
// → 42

使用 use strict, 你就可以获取到更多一点的错误信息:

(function () {
   "use strict";
   a = 42;
   // Error: Uncaught ReferenceError: a is not defined
})();

你可能想知道为什么可以将 "use strict" 放在封装函数的外面。这的确是可以的,不过这样它就会被应用到全局。这还不是太坏,但是如果有代码是来自于其它的库,或者你要把所有的东西都打包到一个文件里面去的话,这样做就会有影响的。

 3. 严格相等

这个比较简短。如果你在 JavaScript 中 (像其它的编程语言中那样)使用 == 来比较 a 和 b,可能会发现其运行的方式有点怪: 如果你有一个字符串和一个数字如下,它们会相等 (==):

"42" == 42
// → true

对于一些明显的缘故 (例如验证操作), 最好就是使用严格等于(===):

"42" === 42
// → false

 4. 使用 && 和 || 来制造点小把戏

根你需要做的事情,你可以使用逻辑操作符来让代码更简短。

取默认值

"" || "foo"
// → "foo"
undefined || 42
// → 42
// Note that if you want to handle 0 there, you need
// to check if a number was provided:
var a = 0;
a || 42
// → 42
// This is a ternary operator—works like an inline if-else statement
var b = typeof a === "number" ? a : 42;
// → 0

不用拿 if 表达式来检查某些东西是不是为真的,你也可以简单地这样做:

expr && doSomething();

// Instead of:
if (expr) {
   doSomething();
}

如果你需要通过 doSomething(): 来决定返回的结果,这样做更酷:

function doSomething () {
   return { foo: "bar" };
}
var expr = true;
var res = expr && doSomething();
res && console.log(res);
// → { foo: "bar" }

你可能不会赞同我在这方面的看法,但像我说的这样做其实效果更理想。如果你并不想像这样来对你的代码进行混淆,但其实这就是那些 JavaScript 简化器实际会做的事情。

如果你来问我,我会说这样做虽然让代码更加简短了,但仍然是可读的。

 5. 对值的类型进行转化

有几种方法可以根据你的想法来进行转化。最常用的方式有如下这些:

// From anything to a number

var foo = "42";
var myNumber = +foo; // shortcut for Number(foo)
// → 42

// Tip: you can convert it directly into a negative number
var negativeFoo = -foo; // or -Number(foo)
// → -42

// From object to array
// Tip: `arguments` is an object and in general you want to use it as array
var args = { 0: "foo", 1: "bar", length: 2 };
Array.prototype.slice.call(args)
// → [ 'foo', 'bar' ]

// Anything to boolean
/// Non non p is a boolean p
var t = 1;
var f = 0;
!!t
// → true
!!f
// → false

/// And non-p is a boolean non-p
!t
// → false
!f
// → true

// Anything to string
var foo = 42;
"" + foo // shortcut for String(foo)
// → "42"

foo = { hello: "world" };
JSON.stringify(foo);
// → '{ "hello":"world" }'

JSON.stringify(foo, null, 4); // beautify the things
// →
// '{
//    "hello": "world"
// }'

// Note you cannot JSON.stringify circular structures
JSON.stringify(window);
// ⚠ TypeError: JSON.stringify cannot serialize cyclic structures.

 6. 代码风格/风格指南

在新的项目中要让所有的文件都遵循相同的代码风格。对于现有的项目,就使用现有的代码风格, 除非你就只是决定要变一变它的风格(提示: 同你的搭档就此进行一下讨论)。甚至你要创建和记录你自己的代码风格,然后一直去遵循它。

现有的一些不同的代码风格如下:

  • Google JavaScript 风格指南

  • airbnb/javascript

  • ... 也还有其它的一些

  • 我的风格指南

 额外的福利小提示:

你应该记住的其它一些重要的 JavaScript 最佳实践就是那些能帮助你对代码进行格式化的工具。下面是其中的一些:

  • js-beautify: 美化你的代码

  • UglifyJS(2): 混淆/最小化你的代码

  • jshint: 检测 JavaScript 代码中的错误或者潜在问题

  • jscs: 可以配置的样式指南检测器

最后一个就是: 不要总是 console.log,要对你的代码进行调试。

祝你编程愉快!

原文地址:https://www.codementor.io/johnnyb/tutorials/javascript-best-practices-du107mvud

Javascript 相关文章推荐
js 创建书签小工具之理论
Feb 25 Javascript
使用Firebug对js进行断点调试的图文方法
Apr 02 Javascript
js文本框输入点回车触发确定兼容IE、FF等
Nov 19 Javascript
jQuery与getJson结合的用法实例
Aug 07 Javascript
jquery zTree异步加载、模糊搜索简单实例分享
Mar 24 Javascript
jQuery的promise与deferred对象在异步回调中的作用
May 03 Javascript
Vue axios 中提交表单数据(含上传文件)
Jul 06 Javascript
提高Node.js性能的应用技巧分享
Aug 10 Javascript
vue实现城市列表选择功能
Jul 16 Javascript
解决vue项目 build之后资源文件找不到的问题
Sep 12 Javascript
JavaScript+HTML实现学生信息管理系统
Apr 20 Javascript
详解JavaScript的计时器和按钮效果设置
Feb 18 Javascript
简单理解Vue条件渲染
Dec 03 #Javascript
学习vue.js条件渲染
Dec 03 #Javascript
浅谈jQuery中Ajax事件beforesend及各参数含义
Dec 03 #Javascript
jquery 判断div show的状态实例
Dec 03 #Javascript
利用浮层使select不可选的实现方法
Dec 03 #Javascript
textarea 在浏览器中固定大小和禁止拖动的实现方法
Dec 03 #Javascript
浅谈jQuery hover(over, out)事件函数
Dec 03 #Javascript
You might like
将OICQ数据转成MYSQL数据
2006/10/09 PHP
PHP学习之整理字符串
2011/04/17 PHP
PHP运行出现Notice : Use of undefined constant 的完美解决方案分享
2012/03/05 PHP
基于PHP服务端图片生成缩略图的方法详解
2013/06/20 PHP
PHP 利用Mail_MimeDecode类提取邮件信息示例
2014/01/26 PHP
利用PHP判断是否是连乘数字串的方法示例
2017/07/03 PHP
php 多继承的几种常见实现方法示例
2019/11/18 PHP
修改js Calendar日历控件 兼容IE9/谷歌/火狐
2013/01/04 Javascript
textarea不能通过maxlength属性来限制字数的解决方法
2014/09/01 Javascript
JS实现模拟风力的雪花飘落效果
2015/05/13 Javascript
js游戏人物上下左右跑步效果代码分享
2015/08/28 Javascript
JavaScript中两个字符串的匹配
2016/06/08 Javascript
Javascript摸拟自由落体与上抛运动原理与实现方法详解
2020/04/08 Javascript
[01:44]《为梦想出发》—联想杯DOTA2完美世界全国高校联赛
2015/09/30 DOTA
[59:00]DOTA2-DPC中国联赛 正赛 Ehome vs PSG.LGD BO3 第一场 3月7日
2021/03/11 DOTA
python简单程序读取串口信息的方法
2015/03/13 Python
Django中信号signals的简单使用方法
2019/07/04 Python
Django时区详解
2019/07/24 Python
快速解决docker-py api版本不兼容的问题
2019/08/30 Python
opencv-python 提取sift特征并匹配的实例
2019/12/09 Python
15行Python代码实现免费发送手机短信推送消息功能
2020/02/27 Python
python中使用you-get库批量在线下载bilibili视频的教程
2020/03/10 Python
Python数据可视化常用4大绘图库原理详解
2020/10/23 Python
基于Python实现粒子滤波效果
2020/12/01 Python
微信小程序“圣诞帽”的实现思路详解
2017/12/28 HTML / CSS
Perfumetrader荷兰:香水、化妆品和护肤品在线商店
2017/09/15 全球购物
澳大利亚著名的纺织品品牌:Canningvale
2020/05/05 全球购物
what is the difference between ext2 and ext3
2013/11/03 面试题
英语硕士生求职简历的自我评价
2013/10/15 职场文书
交通事故调解协议书
2014/04/16 职场文书
学期评语大全
2014/04/30 职场文书
党员弘扬焦裕禄精神思想汇报
2014/09/10 职场文书
2014年驾驶员工作总结
2014/11/18 职场文书
工作证明格式范文
2015/06/15 职场文书
GoLang中生成UUID唯一标识的实现
2021/05/08 Golang
Z-Order加速Hudi大规模数据集方案分析
2022/03/31 Servers