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拦截alert对话框另类应用
Jan 16 Javascript
javascript与css3动画结合使用小结
Mar 11 Javascript
JavaScript实现给定时间相加天数的方法
Jan 25 Javascript
基于JavaScript实现文字超出部分隐藏
Feb 29 Javascript
js获取页面及个元素高度、宽度的代码
Apr 26 Javascript
基于BootStrap Metronic开发框架经验小结【五】Bootstrap File Input文件上传插件的用法详解
May 12 Javascript
微信公众号  提示:Unauthorized API function 问题解决方法
Dec 05 Javascript
TypeScript入门-接口
Mar 30 Javascript
vue做移动端适配最佳解决方案(亲测有效)
Sep 04 Javascript
vue组件命名和props命名代码详解
Sep 01 Javascript
layui对工具条进行选择性的显示方法
Sep 19 Javascript
关于Vue Router的10条高级技巧总结
May 06 Vue.js
简单理解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制作静态网站的模板框架(二)
2006/10/09 PHP
PHP与MySQL开发的8个技巧小结
2010/12/17 PHP
php实现rc4加密算法代码
2012/04/25 PHP
PHP会员找回密码功能的简单实现
2016/09/05 PHP
PHP实现Unicode编码相互转换的方法示例
2020/11/17 PHP
Linux下 php7安装redis的方法
2018/11/01 PHP
PHP如何使用JWT做Api接口身份认证的实现
2020/02/03 PHP
JavaScript replace(rgExp,fn)正则替换的用法
2010/03/04 Javascript
简单谈谈jQuery(function(){})与(function(){})(jQuery)
2014/12/19 Javascript
jquery代码实现简单的随机图片瀑布流效果
2015/04/20 Javascript
javascript省市区三级联动下拉框菜单实例演示
2015/11/29 Javascript
详解关于微信setData回调函数中的坑
2019/02/18 Javascript
vue使用axios上传文件(FormData)的方法
2019/04/14 Javascript
JavaScript从原型到原型链深入理解
2019/06/03 Javascript
js实现带搜索功能的下拉框
2020/01/11 Javascript
nodejs中的异步编程知识点详解
2021/01/17 NodeJs
[01:01:25]DOTA2上海特级锦标赛B组资格赛#2 Fnatic VS Spirit第三局
2016/02/27 DOTA
简单的抓取淘宝图片的Python爬虫
2014/12/25 Python
python中self原理实例分析
2015/04/30 Python
python append、extend与insert的区别
2016/10/13 Python
Python使用asyncio包处理并发详解
2017/09/09 Python
Python动刷新抢12306火车票的代码(附源码)
2018/01/24 Python
python 实现返回一个列表中出现次数最多的元素方法
2019/06/11 Python
Django urls.py重构及参数传递详解
2019/07/23 Python
python 抓包保存为pcap文件并解析的实例
2019/07/23 Python
Pytorch 中retain_graph的用法详解
2020/01/07 Python
python匿名函数lambda原理及实例解析
2020/02/07 Python
python 非线性规划方式(scipy.optimize.minimize)
2020/02/11 Python
纯CSS3编写的的精美动画进度条(无flash/无图像/无脚本/附源码)
2013/01/07 HTML / CSS
为您的家、后院、车库等在线购物:Spreetail
2019/06/17 全球购物
雷蛇美国官网:Razer
2020/04/03 全球购物
TUMI香港官网:国际领先的行李箱、背囊品牌
2021/03/01 全球购物
高一政治教学反思
2014/01/28 职场文书
大二学习计划书范文
2014/04/27 职场文书
浅谈pytorch中stack和cat的及to_tensor的坑
2021/05/20 Python
浅谈Redis缓冲区机制
2022/06/05 Redis