深入理解JavaScript系列(1):编写高质量JavaScript代码的基本要点
来源:互联网 发布:网络缩写英文字母 编辑:程序博客网 时间:2024/05/19 19:40
书写可维护的代码(Writing Maintainable Code )
软件bug的修复是昂贵的,并且随着时间的推移,这些bug的成本也会增加,尤其当这些bug潜伏并慢慢出现在已经发布的软件中时。当你发现bug 的时候就立即修复它是最好的,此时你代码要解决的问题在你脑中还是很清晰的。否则,你转移到其他任务,忘了那个特定的代码,一段时间后再去查看这些代码就需要:
- 花时间学习和理解这个问题
- 花时间去了解应该解决的问题代码
还有问题,特别对于大的项目或是公司,修复bug的这位伙计不是写代码的那个人(且发现bug和修复bug的不是同一个人)。因此,必须降低理解代 码花费的时间,无论是一段时间前你自己写的代码还是团队中的其他成员写的代码。这关系到底线(营业收入)和开发人员的幸福,因为我们更应该去开发新的激动 人心的事物而不是花几小时几天的时间去维护遗留代码。
另一个相关软件开发生命的事实是,读代码花费的时间要比写来得多。有时候,当你专注并深入思考某个问题的时候,你可以坐下来,一个下午写大量的代码。
你的代码很能很快就工作了,但是,随着应用的成熟,还会有很多其他的事情发生,这就要求你的进行进行审查,修改,和调整。例如:
- bug是暴露的
- 新功能被添加到应用程序
- 程序在新的环境下工作(例如,市场上出现新型浏览器)
- 代码改变用途
- 代码得完全从头重新,或移植到另一个架构上或者甚至使用另一种语言
由于这些变化,很少人力数小时写的代码最终演变成花数周来阅读这些代码。这就是为什么创建可维护的代码对应用程序的成功至关重要。
可维护的代码意味着:
- 可读的
- 一致的
- 可预测的
- 看上去就像是同一个人写的
- 已记录
最小全局变量(Minimizing Globals)
JavaScript通过函数管理作用域。在函数内部声明的变量只在这个函数内部,函数外面不可用。另一方面,全局变量就是在任何函数外面声明的或是未声明直接简单使用的。
每个JavaScript环境有一个全局对象,当你在任意的函数外面使用this的时候可以访问到。你创建的每一个全部变量都成了这个全局对象的属 性。在浏览器中,方便起见,该全局对象有个附加属性叫做window,此window(通常)指向该全局对象本身。
myglobal = "hello";// 不推荐写法console.log(myglobal); // "hello"console.log(window.myglobal); // "hello"console.log(window["myglobal"]); // "hello"console.log(this.myglobal); // "hello"
全局变量的问题
function sum(x, y) { // 不推荐写法: 隐式全局变量 result = x + y; return result;}
另一个创建隐式全局变量的反例就是使用任务链进行部分var声明。下面的片段中,
a
是本地变量但是b却是
全局变量,这可能不是你希望发生的:// 反例,勿使用 function foo() { var a = b = 0; // ...}
此现象发生的原因在于这个从右到左的赋值,首先,是赋值表达式
b = 0
,此情况下b是未声明的。这个表达式的返回值是0,然后这个0就分配给了通过var定义的这个局部变量a。换句话说,就好比你输入了:var a = (b = 0);
如果你已经准备好声明变量,使用链分配是比较好的做法,不会产生任何意料之外的全局变量,如:
function foo() { var a, b; // ... a = b = 0; // 两个均局部变量}
忘记var的副作用(Side Effects When Forgetting var)
delete
操作符让变量未定义的能力。- 通过var创建的全局变量(任何函数之外的程序中创建)是不能被删除的。
- 无var创建的隐式全局变量(无视是否在函数中创建)是能被删除的。
delete
操作符删除的,而变量是不能的:// 定义三个全局变量var global_var = 1;global_novar = 2; // 反面教材(function () { global_fromfunc = 3; // 反面教材}());// 试图删除delete global_var; // falsedelete global_novar; // truedelete global_fromfunc; // true// 测试该删除alert(typeof global_var); // "number"alert(typeof global_novar); // "undefined"alert(typeof global_fromfunc); // "undefined"
访问全局对象(Access to the Global Object)
单var形式(Single var Pattern)
在函数顶部使用单var语句是比较有用的一种形式,其好处在于:
- 提供了一个单一的地方去寻找功能所需要的所有局部变量
- 防止变量在定义之前使用的逻辑错误
- 帮助你记住声明的全局变量,因此减少了全局变量//zxx:此处我自己是有点晕乎的…
- 少代码(类型啊传值啊单线完成)
function func() { var a = 1, b = 2, sum = a + b, myobject = {}, i, j; // function body...}
您可以使用一个var语句声明多个变量,并以逗号分隔。像这种初始化变量同时初始化值的做法是很好的。这样子可以防止逻辑错误(所有未初始化但声明的变量的初始值是
undefined
)和增加代码的可读性。在你看到代码后,你可以根据初始化的值知道这些变量大致的用途,例如是要当作对象呢还是当作整数来使。预解析:var散布的问题(Hoisting: A Problem with Scattered vars)
// 反例myname = "global"; // 全局变量function func() { alert(myname); // "undefined" var myname = "local"; alert(myname); // "local"}func();在这个例子中,你可能会以为第一个alert弹出的是”global”,第二个弹出”loacl”。这种期许是可以理解的,因为在第一个alert 的时候,myname未声明,此时函数肯定很自然而然地看全局变量myname,但是,实际上并不是这么工作的。第一个alert会弹 出”undefined”是因为myname被当做了函数的局部变量(尽管是之后声明的),所有的变量声明当被悬置到函数的顶部了。因此,为了避免这种混 乱,最好是预先声明你想使用的全部变量。
for循环(for Loops)
for-in循环(for-in Loops)
(不)扩展内置原型((Not) Augmenting Built-in Prototypes)
增加内置的构造函数原型(如Object(), Array(), 或Function())挺诱人的,但是这严重降低了可维护性,因为它让你的代码变得难以预测。使用你代码的其他开发人员很可能更期望使用内置的 JavaScript方法来持续不断地工作,而不是你另加的方法。
另外,属性添加到原型中,可能会导致不使用hasOwnProperty属性时在循环中显示出来,这会造成混乱。
switch模式(switch Pattern)
避免隐式类型转换(Avoiding Implied Typecasting )
var zero = 0;if (zero === false) { // 不执行,因为zero为0, 而不是false}// 反面示例if (zero == false) { // 执行了...}
避免(Avoiding) eval()
parseInt()下的数值转换(Number Conversions with parseInt())
var month = "06", year = "09";month = parseInt(month, 10);year = parseInt(year, 10);
此例中,如果你忽略了基数参数,如parseInt(year),返回的值将是0,因为“09”被当做8进制(好比执行 parseInt( year, 8 )),而09在8进制中不是个有效数字。
替换方法是将字符串转换成数字,包括:
+"08" // 结果是 8Number("08") // 8
编码规范(Coding Conventions)
缩进(Indentation)
花括号{}(Curly Braces)
左花括号的位置(Opening Brace Location)
空格(White Space)
分隔单词(Separating Words)
其它命名形式(Other Naming Patterns)
// 珍贵常数,只可远观var PI = 3.14, MAX_WIDTH = 800;
还有另外一个完全大写的惯例:全局变量名字全部大写。全部大写命名全局变量可以加强减小全局变量数量的实践,同时让它们易于区分。
注释(Writing Comments)
关于作者(About the Author )
同步与结束语
- 深入理解JavaScript系列(1):编写高质量JavaScript代码的基本要点javascript
- (转)深入理解JavaScript系列(1):编写高质量JavaScript代码的基本要点
- 深入理解JavaScript系列(1):编写高质量JavaScript代码的基本要点
- 深入理解JavaScript系列(1):编写高质量JavaScript代码的基本要点
- 深入理解JavaScript系列(1):编写高质量JavaScript代码的基本要点
- 深入理解JavaScript系列(1):编写高质量JavaScript代码的基本要点
- 深入理解JavaScript系列(1):编写高质量JavaScript代码的基本要点
- 深入理解JavaScript系列(1):编写高质量JavaScript代码的基本要点
- 深入理解JavaScript系列(1):编写高质量JavaScript代码的基本要点
- 深入理解JavaScript系列(1):编写高质量JavaScript代码的基本要点
- 深入理解JavaScript系列(1):编写高质量JavaScript代码的基本要点
- 深入理解JavaScript系列 ----(1):编写高质量JavaScript代码的基本要点
- 深入理解JavaScript系列(1):编写高质量JavaScript代码的基本要点
- 深入理解JavaScript系列(1):编写高质量JavaScript代码的基本要点
- 深入理解JavaScript系列(1):编写高质量JavaScript代码的基本要点
- 深入理解JavaScript系列(1):编写高质量JavaScript代码的基本要点
- 深入理解JavaScript系列(1):编写高质量JavaScript代码的基本要点
- 深入理解JavaScript系列(1):编写高质量JavaScript代码的基本要点
- 修改监听端口后oem的操作
- 可变类型开放数组Demo
- 采用execSQL()和rawQuery()方法完成数据的添删改查
- 如何让虚拟目录里面的webconfig不继承网站的设置
- [RTT例程练习] 1.7 优先级翻转之优先级继承
- 深入理解JavaScript系列(1):编写高质量JavaScript代码的基本要点
- 对话框中WaitForSingleObject等待线程退出导致程序阻塞的原因及解决
- BlowFish算法加密解密
- 诉说一个屌丝20多年的点点滴滴
- shell中sed的使用
- spring和BlazeDS 集成配置后台
- VIM下,在文件及目录中查找字符串的方法 (vimgrep)
- poj 1252 Euro Efficiency(多次完全背包)
- 使用TSung对Jabber服务器openfire进行压力测试