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 相关文章推荐
Ext.MessageBox工具类简介
Dec 10 Javascript
js动态为代码着色显示行号
May 29 Javascript
深入理解Javascript里的依赖注入
Mar 19 Javascript
jQuery中offset()方法用法实例
Jan 16 Javascript
JSON格式的键盘编码对照表
Jan 29 Javascript
javaScript中Math()函数注意事项
Jun 18 Javascript
Node.js 条形码识别程序构建思路详解
Feb 14 Javascript
全面解析Angular中$Apply()及$Digest()的区别
Aug 04 Javascript
详解jquery easyui之datagrid使用参考
Dec 05 Javascript
微信小程序 图片边框解决方法
Jan 16 Javascript
vue项目中使用Svg的方法
Oct 24 Javascript
JS+css3实现幻灯片轮播图
Aug 14 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
浏览器预览PHP文件时顶部出现空白影响布局分析原因及解决办法
2013/01/11 PHP
php jsonp单引号转义
2014/11/23 PHP
Yii2.0中使用js异步删除示例
2017/03/10 PHP
ThinkPHP框架表单验证操作方法
2017/07/19 PHP
把jquery 的dialog和ztree结合实现步骤
2013/08/02 Javascript
jQuery封装的获取Url中的Get参数示例
2013/11/26 Javascript
Javascript selection的兼容性写法介绍
2013/12/20 Javascript
自定义函数实现IE7与IE8不兼容js中trim函数的问题
2015/02/03 Javascript
深入理解JavaScript的React框架的原理
2015/07/02 Javascript
jquery checkbox的相关操作总结
2016/10/17 Javascript
BootStrap 弹出层代码
2017/02/09 Javascript
Javascript中将变量转换为字符串的三种方法
2017/09/19 Javascript
浅谈AngularJS中$http服务的简单用法
2018/05/15 Javascript
js canvas实现二维码和图片合成的海报
2020/11/19 Javascript
Vue中component标签解决项目组件化操作
2020/09/04 Javascript
VUE+Element实现增删改查的示例源码
2020/11/23 Vue.js
Python中创建字典的几种方法总结(推荐)
2017/04/27 Python
Python实现将SQLite中的数据直接输出为CVS的方法示例
2017/07/13 Python
分析Python读取文件时的路径问题
2018/02/11 Python
Python常见字典内建函数用法示例
2018/05/14 Python
python实现时间o(1)的最小栈的实例代码
2018/07/23 Python
解决python selenium3启动不了firefox的问题
2018/10/13 Python
python3+PyQt5 自定义窗口部件--使用窗口部件样式表的方法
2019/06/26 Python
Python 实现大整数乘法算法的示例代码
2019/09/17 Python
让IE支持HTML5的方法
2012/12/11 HTML / CSS
详解前端HTML5几种存储方式的总结
2016/12/27 HTML / CSS
俄罗斯极限运动网上商店:Board Shop №1
2020/12/18 全球购物
护士辞职信范文
2014/01/19 职场文书
模具毕业生推荐信
2014/02/15 职场文书
《望庐山瀑布》教学反思
2014/04/22 职场文书
爱国演讲稿500字
2014/05/04 职场文书
2016年小学生新年寄语
2015/08/18 职场文书
2016年端午节红领巾广播稿
2015/12/18 职场文书
《家》读后感:万惜拯救,冷暖自知
2019/09/25 职场文书
MySQL获取所有分类的前N条记录
2021/05/07 MySQL
tensorflow中的数据类型dtype用法说明
2021/05/26 Python