您的位置:首页 > Web前端 > JavaScript

编写高质量的JS代码(变量的声明和for循环)

2016-01-06 00:10 609 查看
才华横溢的Stoyan Stefanov,在他写的由O’Reilly初版的新书《JavaScript Patterns》(JavaScript模式)中,具体一点就是编写高质量JavaScript的一些要素,例如避免全局变量,使用单变量声明,在循环中预缓存length(长度)遵循代码阅读,以及更多。

1、书写可维护的代码

软件bug的修复是昂贵的,并且随着时间的推移,这些bug的成本也会增加,特别对于大的项目或是公司,修复bug的不是写代码的那个人。因此,必须降低理解代码花费的时间,无论是一段时间前你自己写的代码还是团队中的其他成员写的代码。

并且,当随着应用的成熟,还会有很多其他的事情发生,这就要求你进行进行审查,修改,和调整。这就是为什么创建可维护的代码对应用程序的成功至关重要。

可维护的代码意味着:

可读的

一致的

可预测的

看上去是同一个人写的

已记录

2、全局变量的问题

因为js通过函数来管理变量的作用域,在函数内部声明的变量只在这个函数内部,函数外面不可用。另一方面,全局变量就是在任何函数外面声明的或是未声明直接简单使用的。

每个JavaScript环境有一个全局对象window,当你在任意的函数外面使用this的时候可以访问到。你创建的每一个全部变量都成了这个全局对象的属性window(通常)指向该全局对象本身。下面的代码片段显示了如何在浏览器环境中创建和访问的全局变量:

var checkThis = function(){
alert( this.x);
};
var x = 'this is a property of window';
var obj = {};
obj.x = 100;
obj.y = function(){ alert( this.x ); };
obj.y(); //弹出 100
checkThis(); //弹出 'this is a property of window'


在JavaScript语言中,this的定义是:this是包含它的函数作为方法被调用时所属的对象。

这里为什么会弹出 ‘this is a property of window’,可能有些让人迷惑。在JavaScript的变量作用域里有一条规则“全局变量都是window对象的属性”。当执行checkThis() 时相当于window.checkThis(),因此,此时checkThis函数体内的this关键字的指向变成了window对象,而又因为window对象又一个x属性(’thisis a property of window’),所以会弹出 ‘thisis a property of window’。

同样是全局变量的问题,如果你定义了一个全局变量,你的JavaScript应用程序和web页面上的所有代码都共享了这些全局变量,他们住在同一个全局命名空间,所以当程序的两个不同部分定义同名但不同作用的全局变量的时候,命名冲突在所难免。

例如:web页面包含不是该页面开发者所写的代码,像是

第三方的JavaScript库

广告方的脚本代码

比方说,该第三方脚本定义了一个全局变量,叫做result;接着,在你的函数中也定义一个名为result的全局变量。其结果就是后面的变量覆盖前面的,第三方脚本就不能正常运行了!

那么,js中通过var声明和不通过var声明的变量的区别是什么呢?

JS中变量申明分显式申明和隐式申明。

Var i=100 显示申明

i=100 隐式申明

如果在函数中,使用var关键字进行显式申明的,那么变量是做为局部变量;而没有用var关键字,使用直接赋值方式声明的是全局变量。

而,当我们使用访问一个没有声明的变量时,JS会报错。而当我们给一个没有声明的变量赋值时,JS不会报错,相反它会认为我们是要隐式申明一个全局变量。

var num = 1是在当前域(例如函数中)中声明变量,如果在方法中声明,则为局部变量;如果是在全局域中声明,则为全局变量。

而num = 1,事实上是对属性赋值操作。首先,它会尝试在当前作用域链(如在方法中声明,则当前作用域链代表全局作用域和方法局部作用域)中解析 num; 如果在任何当前作用域链中找到num,则会执行对num属性赋值; 如果没有找到num,它才会在全局对象(即当前作用
4000
域链的最顶层对象,如window对象)中创造num属性并赋值。

另外,还有一种创建了隐式变量的例子,即使用任务链进行部分var声明。下面的片段中,a是本地变量但是b却是全局变量,这可能不是你希望发生的:

// 反例,勿使用
function foo() {
var a = b = 0;
// ...
}


这句话的意思相当于var a = (b=0);

所以,如果我们准备好了要用任务链进行赋值,我们首先要var a,b;然后通过a=b=0;赋值,这样就不会出现任何问题了

那么,命名变量最好的方式是在顶部的单var形式



function func() {
var a = 1,
b = 2,
sum = a + b,
myobject = {},
i,
j;
// function body...
}


您可以使用一个var语句声明多个变量,并以逗号分隔。像这种初始化变量同时初始化值的做法可以防止逻辑错误并增加可读性。

关于for循环的问题

在for循环中,你可以循环取得数组或是数组类似对象的值,通常的循环形式如下:

// 次佳的循环
for (var i = 0; i < myarray.length; i++) {
// 使用myarray[i]做点什么
}


这种形式的循环的不足在于每次循环的时候数组的长度都要去获取下。这回降低你的代码,尤其当myarray不是数组,而是一个HTMLCollection对象的时候。

HTMLCollections指的是DOM方法返回的对象,例如:

document.getElementsByName()

document.getElementsByClassName()

document.getElementsByTagName()

集合的麻烦在于它们实时查询基本文档(HTML页面)。这意味着每次你访问任何集合的长度,你要实时查询DOM,而DOM操作一般都是比较昂贵的。

这就是为什么当你循环获取值时,缓存数组(或集合)的长度是比较好的形式,正如下面代码显示的:(即先给数组长度定义一个变量值)

for (var i = 0, max = myarray.length; i < max; i++) {
// 使用myarray[i]做点什么
}


这样,在这个循环过程中,你只检索了一次长度值。

最后一个需要对循环进行调整的是使用下面表达式之一来替换i++。

i = i + 1

i += 1
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  javascript 全局变量