尽量少用全局变量

大量使用全局变量会导致的后果

全局变量创建以后会在整个JavaScript应用和Web页面中共享。所有的全局变量都存在于一个全局命名空间内,很容易发生冲突

不知不觉创建了全局变量

其原因在于JavaScript的两个特性,第一个是JavaScript可直接使用变量而无需声明,第二个是JavaScript的暗示全局变量的概念,即任何变量如果未经声明,就为全局对象所有

为了避免我们无意间创建了全局变量 我们可以使用var声明变量

另一种创建暗示全局变量的反模式是带有var声明的链式赋值。

产生上面结果的原因是 JavaScript的从右到左的操作符优先级 它的执行顺序是这样的

```javascript
var a = (b = 0); ```

解决方案也很简单 就是对链式赋值的所有变量都进行赋值,如下代码所示:

```javascript

  function demo(){
var a,b;
a = b = 0;
} ```

另一个避免全局变量大量使用的原因在于代码移植,你的代码在当前环境(主机)运行是没有问题的,但换个环境,全局变量可能会和存在于其他环境的变量发生冲突。

全局变量的释放

暗示全局变量和明确定义的全局变量有细微的不同,不同之处在于是否能用delete销毁,代码如下:

以上代码说明暗示全局变量可以通过delete删除,而var定义则不能

访问全局变量

在浏览器下,可通过window属性在代码的任意位置访问到全局变量,但是也可能发生意外(声明了一个名为window的局部变量)。

在其他环境下(如NodeJS),window就不叫window了,NodeJS下整个Runtime时期的全局变量是global,顾用window还不够严谨。

解决方案代码如下:

```javascript

  var global = (function(){
return this;
}()); ```

按这种方式通常都能获取全局对象,因为this在函数内部作为一个函数调用(不是通过构造器创建也不是通过call,apply指定),往往指向全局对象

但是如果你的代码运行在ES5的严格模式下,就不能这样用了,解决代码如下:

变量及函数声明的提升

JavaScript允许在函数的任意地方声明多个变量或函数,无论在哪里声明都等同于在函数顶部声明,这就是所谓的提升

以上代码说明 var v1 被看做是局部变量的声明,所以打印出来的是undefined 这其实还涉及到一个变量对象(Variable Object)的问题,打印的时候他会先在Variable Object中找,如果找不到才会到window中去找,如果发现有了,则直接打印出来

for循环的优化

看到这里,你可能会觉得奇怪,for还有可以优化的地方吗?谈不上优化,就是一些注意点

闲话不多说直接上代码:

```javascript
//经典的for循环
for(var i = 0; i < array.length; i++){
//对array[i]进行操作
}
```

这种模式的问题在于每次循环都要访问数组的length,如果是数组还好,影响不是很大(速度变慢)。但是如果遍历的是DOM集合,我们知道在document下操作DOM是很耗性能的,而如果我们将length用变量保存起来,从而避免了每次循环对DOM的查询,在所有的浏览器中都会大大降低性能的损耗,其中在safari中速度会提高3倍,IE7中会提高170倍之多

还有一个可以改进的是可以通过:

```javascript
var array = [],len = array.length ;
for(len,len--){
//处理array[len]
}
```

这种模式 有2个好处,使用了最少的变量,逐步减至0,因为同0比较 比 同数组的长度比较速度更快

还有一种while的模式,和这个类似,我就不贴代码了(嘿嘿)

不要增加内置对象的原型

以前喜欢写这种代码,被我英明的 “会哥” 提醒了一下,专门去看了下,反模式的典型啊。。。自我检讨下

增加内置构造函数(Object,Array,Function)的原型是很爽的(埋下的坑迟早要填。。),但是这可能会严重影响可维护性,因为这将使你的代码变得更加不可预测,比如你重写了Array的slice方法,而别的工程师不知道,他得不到预期的结果(比全局对象污染更严重),如果一定要写也必须先准确的记录下来,并和团队交流清楚

应该避免的一些小细节

避免使用隐式类型转换

JavaScript 在执行比较语句的时候会进行隐式类型转换,这也是为什么执行 false==0 或 "" == 0 这类比较语句会返回true的原因

为了避免隐式转换造成的混淆不清,最好在使用比较语句的时候使用 === 和!===


避免使用eval()

eval 会将任意字符串当作JavaScript代码来执行(ES5 严格模式下使用eval会报错),eval会执行被修改过的代码(可能被客户端修改),会产生一些安全隐患

eval的替代方案 使用浏览器自带的方法来解析JSON请求 JSON.parse() ,对于不支持parse的可以使用来自JSON.org的类库,还有就是通过setTimeout,setInterval,和function的构造函数来传递参数,在大部分情况下也会导致类似eval的隐患,如下代码所示:

```javascript
//反模式
setTimeout("func()" , 1000);
setTimeout("func(1,2,3)" , 1000);
//推荐的模式
setTimeout(func , 1000);
setTimeout(function(){
func(1,2,3);
} , 1000);
如果传给setTimeout是字符串,JavaScript仍然会去以程序代码的方式去执行传递过来的字符串,如果一定要用eval,可以考虑用new Function()的方式来替代eval,代码如下:
var code = "console.log(5)"
new Function(code)(); //5
```

使用parseInt的第二个参数

通常第二个参数我们都是忽略,但是有时候会发生一些bug,比如如果我传的字符串是以0开头的就会出现错误,他会不确定是8进制还是10进制,所以最好还是加上进制。另外将一个字符串转换成数值有更快的方法,代码如下:

```javascript
+ “08” //8
Number(“08”) //8
```

这些方法比parseInt快很多,parseInt是解析而不是简单的转换,例如输入“08 soso” 除了parseInt 其他的都会返回NaN

运行JSLint

JSLint 可以检查你的代码,提前发现你的代码有哪些不足,写完代码后在JSLint上跑一遍,这是很好的编程模式(BUG伤不起啊)

后记:

第一次写这么长的博客,文中难免有错误之处,如果能指出感激不进

这篇读书笔记,部分加入了自己工作中遇到的需求加以理解,如有不对之处,请联系我,共同进步

初涉JavaScript模式 (2) : 基本技巧的更多相关文章

  1. 初涉JavaScript模式系列 阶段总结及规划

    总结 不知不觉写初涉JavaScript模式系列已经半个月了,没想到把一个个小点进行放大,竟然可以发现这么多东西. 期间生怕对JS的理解不到位而误导各位,读了很多书(个人感觉JS是最难的oo语言),也 ...

  2. 初涉JavaScript模式 (13) : 代码复用 【上】

    引子 博客断了一段时间,不是不写,一是没时间,二是觉得自己沉淀不够,经过一段时间的学习和实战,今天来总结下一个老生常谈的东西: 代码复用. 为何复用 JS门槛低,故很多人以为写几个特效就会JS,其实真 ...

  3. 初涉JavaScript模式 (12) : 沙箱模式

    引子 上一篇说了模块模式,而对于其中的命名空间模式其实也是有着一些问题,比如每添加一个模块或则深入叠加都会导致长命名,并且对于多个库的不同版本同时运行,一不小心就会污染全局标识,而这两天也发现了JSe ...

  4. 初涉JavaScript模式 (11) : 模块模式

    引子 这篇算是对第9篇中内容的发散和补充,当时我只是把模块模式中的一些内容简单的归为函数篇中去,在北川的提醒下,我才发觉这是非常不严谨的,于是我把这些内容拎出来,这就是这篇的由来. 什么是模块模式 在 ...

  5. 初涉JavaScript模式 (10) : 函数 【进阶用法】

    写在前面 不知不觉写到第10篇了.这篇写起来很忐忑,终于和高级搭上边了(呵呵),这篇我们 主要 说一下 JS 方法的部分高级用法(我知道的),笔者水平有限,难免有错.废话不多少,进入正文. 初始化 我 ...

  6. 初涉JavaScript模式 (9) : 函数 【常用方式】

    回调模式 上一篇,对JavaScript函数进行了大体的介绍,这一篇对一些在工作中经常遇到的情况进行扩展. 在工作中,我们经常遇到很多需求,比如现在有一个需求: 一栋10层的大楼,当我们在坐电梯时,电 ...

  7. 初涉JavaScript模式 (7) : 原型模式 【三】

    组合使用构造函数模式和原型模式 上篇,我们提到了原型模式的缺点,就是每个实例不能拥有自己的属性,因为纯原型模式所有的属性都是公开给每个实例的,故我们可以组合使用构造函数模式和原型模式.构造函数用来定义 ...

  8. 初涉JavaScript模式 (6) : 原型模式 【二】

    原型与in操作符 有两种方式使用in操作符:单独使用和在for-in循环中使用. 在单独使用时,in操作符会遍历实例公开(可枚举)的属性,如果找到该指定属性则返回true,无论该指定属性是存在与实例中 ...

  9. 初涉JavaScript模式 (5) : 原型模式 【一】

    什么是原型模式? 原型模式(prototype)是指用原型实例指向创建对象的种类,并且通过拷贝这些原型创建新的对象.--引自JavaScript设计模式 我们创建的每一个函数都有一个prototype ...

随机推荐

  1. 【单调队列】Vijos P1771 瑞士轮 (NOIP2011普及组第三题)

    题目链接: https://vijos.org/p/1771 题目大意: 给定2N个人(N<=100 000)和其初始分数.能力值(能力两两不同),比赛M次(M<=50),每次PK都是按分 ...

  2. ASP.Net MVC-Web API使用Entity Framework时遇到Loop Reference

    原文地址:http://www.it165.net/pro/html/201210/3932.html 最近开始研究Web API,运气不错第一个测试项目就遇到问题@@-当新增Control时选择[A ...

  3. String Problem - HDU 3374 (kmp+最大最小表示)

    题目大意:有一个字符串长度为N的字符串,这个字符串可以扩展出N个字符串,并且按照顺序编号,比如串  ” SKYLONG “ SKYLONG 1 KYLONGS 2 YLONGSK 3 LONGSKY ...

  4. poj1042

    题目大意:去捕鱼 约翰去参加一个垂钓旅行,他有h小时可以使用在该地区有n (2 <= n <= 25) 个湖泊可以沿着一个单一的路到达,约翰从湖泊1开始,但是它可以在任何湖泊结束他如果想, ...

  5. Hadoop入门--HDFS(单节点)配置和部署 (一)

    一 配置SSH 下载ssh服务端和客户端 sudo apt-get install openssh-server openssh-client 验证是否安装成功 ssh username@192.16 ...

  6. 操作SharedPreferences的注意点

    如果使用SharedPreferences用于数据存取,大部分人喜欢使用如下代码: public void writeSharedprefs(int pos) { SharedPreferences  ...

  7. android图片缓存框架Android-Universal-Image-Loader

    http://blog.csdn.net/king_is_everyone/article/details/34107081 最近跟同学们做了一个创业项目,其实跟以前做项目不同,以前大多数都是做web ...

  8. 如何理解oracle 11g scan ip

    如何理解oracle 11g scan ip   在11.2之前,client链接数据库的时候要用vip,假如你的cluster有4个节点,那么客户端的tnsnames.ora中就对应有四个主机vip ...

  9. 使用Dreamwaver cc中的SVN功能,用于传输BAE和SAE中的文件

    前沿: 假期使用BAE和SAE开发应用,两个服务器都需要通过SVN提交代码,因为平时大多使用Dreamwaver,所以查了查资料,通过Subversion方便了开发. 因为网上的资料都不全,所以根据自 ...

  10. BAT染指影视制作 欲全面撬开互联网粉丝经济

    预測: 或靠"用户"模式盈利 除了内容制作,电影发行也在遭遇互联网模式的冲击. 除了给片方支付高额保底以外,随着市场竞争激烈.新进入者都在争夺好片的发行权. 业内预測.再往后,发行 ...