我的NodeJs学习小结(一)


Posted in NodeJs onJuly 06, 2014

 这第一篇就谈谈NodeJs的一些编程细节吧。

1、遍历数组

for (var i=0, l=arr.length; i<l; i++)

      这样写的一个好处就是让每次循环少一步获取数组对象长度的操作,数组长度越长,价值越明显。

2、判断变量的真假

if (a) {...} //a='', a='0', a=[], a={}

      if条件判断的结果分别是:false, true, true, true。这个结果和PHP的结果是不同的,不要混淆。还需要区分它和非恒等判断相似的情况。

3、0值非恒等判断

1 if (0 == '0') {...} //true
2 if (0 == []) {...} //true
3 if (0 == [0]) {...} //true
4 if (0 == {}) {...} //false
5 if (0 == null) {...} //false
6 if (0 == undefined) {...} //false

      其实还有很多这种诡异的判断,我只列出了较为常见的。如果想弄明白其中的规则,请参阅我的另一篇博文:【JavaScript】深入分析JavaScript的关系运算和if语句。

4、parseInt的陷阱

var n = parseInt(s); //s='010'

        该语句执行后n值为8,而不是10。虽然很多人知道这一点,但是编程中难免会出错,我深有体会。所以,最好按下面的方式来写,就不会出错了。

var n = parseInt(s, 10);

5、变量在使用前一定要先声明

      虽然,直接使用变量而不声明也不会出错,但是,这样写是很容易出错的。因为解释器会把它解释成全局变量,很容易和其他全局变量重名而导致出错。所以,一定要养成变量使用前要先声明的好习惯。

6、循环中存在异步的情况

for (var i=0, l=arr.length; i<l; i++) {
 var sql = "select * from nx_user";
  db.query(sql, function(){
    sys.log(i + ': ' + sql);
  }); //db.query为表查询操作,是异步操作
}

      你会发现,输出的结果都是相同的,而且是当i=arr.length-1时的输出内容。因为JavaScript是单线程的,它会先执行完整个循环的同步内容之后,才去执行其中的异步操作。代码中的匿名回调函数就是一个异步回调。执行到该函数的时候,for循环以及后面的一些同步操作都已经执行完毕。出于闭包原则,该函数会保留for循环的最后一次循环的sql变量和i变量的内容,所以才会导致错误的结果。

      那怎么办呢?解决方法有两种,一种是使用立即函数,如下:

for (var i=0, l=arr.length; i<l; i++) {
  var sql = "select * from nx_user";
  (function(sql, i){
    db.query(sql, function(){
      sys.log(i + ': ' + sql);
    }); //db.query为表查询操作,是异步操作
  })(sql, i);
}

       还有一种方法是将异步操作部分提取出来,单写一个函数,如下:

var outputSQL = function(sql, i){
   db.query(sql, function(){
      sys.log(i + ': ' + sql);
  }); //db.query为表查询操作,是异步操作
}

for (var i=0, l=arr.length; i<l; i++) {
  var sql = "select * from nx_user";
  outputSQL(sql, i); 
}

7 、在对大量数据作处理时,尽量避免循环嵌套。

      因为循环嵌套的处理时间会随着数据量的增加成指数级增长,所以应尽量避免。遇到这种情况,如果没有更好的办法,一般采取的策略是以空间换时间,即建立一张二级循环数据的Hash映射表。当然,还要具体情况具体分析。还有一点要说的是,某些方法本身就是一个循环体,如Array.sort()(该方法应该是用了两层循环实现),在使用的时候需加注意。

8、尽量避免递归调用。

      递归调用的优点是代码简洁,实现简单,而它的缺点很重要,说明如下:

      (1)函数栈的大小会随着递归层次成线性增长,而函数栈是有上限值的,当递归达到一定层数后函数栈就会溢出,从而导致程序出错;

      (2)每递归一层都会增加额外的压栈和出栈操作,即函数调用过程中的保存现场和恢复现场。

      所以,应尽量避免递归调用。

9、关于模块文件的作用域隔离。

      Node在编译JavaScript模块文件的时候,已经对其内容进行了头尾包装,如下:

(function(exports, require, module, __filename, __dirname){
  你的JavaScript文件代码
});

从而使每个模块文件之间进行了作用域隔离。所以,当你编写NodeJs模块文件的时候,不需要自己再加一层作用域隔离封装了。如下面的代码格式,只会额外增加一层函数调用,是不推荐的:

(function(){
  ... ...
})();

 10、数组和对象不要混用

      下面是错误代码的示例:

var o = [];
o['name'] = 'LiMing';

      数组和对象混用可能会导致不可预知的错误。我的一个同事就遇到过一个很奇怪的问题,先看代码:

var o = [];
o['name'] = 'LiMing';
var s = JSON.stringify(o);

       他本以为对象o的name属性会在JSON串中,结果就是没有。当时我也很奇怪,但我有预感到是数组和对象混用的问题,试了一下,果然是它的问题。后来我在ECMA规范中查到,数组在序列化时是按JA规则进行的。所以,要养成一个好的编程习惯,正确使用数组和对象,不要混用。

11、promise优雅编程

       相信接触过nodeJs的人都有过这样的体验,当异步回调里嵌套异步回调的时候,代码就显得很混乱,缺乏易读性。nodeJs的这一窘境可以借助promise来克服。promise就像一个雕琢器,让你的代码变得优雅、美观。promise有个A+规范,网上有几种实现方式,可以参阅。

NodeJs 相关文章推荐
nodejs分页类代码分享
Jun 17 NodeJs
Nodejs学习笔记之入门篇
Apr 16 NodeJs
浅谈Nodejs应用主文件index.js
Aug 28 NodeJs
nodejs简单实现操作arduino
Sep 25 NodeJs
nodejs个人博客开发第二步 入口文件
Apr 12 NodeJs
nodeJS实现简单网页爬虫功能的实例(分享)
Jun 08 NodeJs
nodejs模块学习之connect解析
Jul 05 NodeJs
nodejs结合socket.io实现websocket通信功能的方法
Jan 12 NodeJs
nodejs同步调用获取mysql数据时遇到的大坑
Mar 02 NodeJs
M2实现Nodejs项目自动部署的方法步骤
May 05 NodeJs
nodejs读取图片返回给浏览器显示
Jul 25 NodeJs
nodeJs的安装与npm全局环境变量的配置详解
Jan 06 NodeJs
nodejs中使用monk访问mongodb
Jul 06 #NodeJs
nodejs之请求路由概述
Jul 05 #NodeJs
Nodejs中自定义事件实例
Jun 20 #NodeJs
Nodejs sublime text 3安装与配置
Jun 19 #NodeJs
nodejs实现黑名单中间件设计
Jun 17 #NodeJs
nodejs分页类代码分享
Jun 17 #NodeJs
nodejs npm包管理的配置方法及常用命令介绍
Jun 05 #NodeJs
You might like
PHP生成UTF8文件的方法
2010/05/15 PHP
CI框架开发新浪微博登录接口源码完整版
2014/05/28 PHP
php readfile()修改文件上传大小设置
2017/08/11 PHP
Laravel 5.5 的自定义验证对象/类示例代码详解
2017/08/29 PHP
Laravel程序架构设计思路之使用动作类
2018/06/07 PHP
JavaScript 拾碎[三] 使用className属性
2010/10/16 Javascript
基本jquery的控制tabs打开的数量的代码
2010/10/17 Javascript
jQuery.clean使用方法及思路分析
2013/01/07 Javascript
jQuery删除节点的三个方法即remove()detach()和empty()
2013/12/27 Javascript
javascript 10进制和62进制的相互转换
2014/07/31 Javascript
jQuery实现列表自动滚动循环滚动展示新闻
2014/08/22 Javascript
jquery处理json对象
2014/11/03 Javascript
JS模式之简单的订阅者和发布者模式完整实例
2015/06/30 Javascript
JavaScript的Ext JS框架中的GridPanel组件使用指南
2016/05/21 Javascript
浅谈DOCTYPE对$(window).height()取值的影响
2016/07/21 Javascript
详解Vue双向数据绑定原理解析
2017/09/11 Javascript
JavaScript文本特效实例小结【3个示例】
2018/12/22 Javascript
vue项目前端埋点的实现
2019/03/06 Javascript
解决Vue-cli无法编译es6的问题
2020/10/30 Javascript
[01:15:15]VG VS EG Supermajor小组赛B组胜者组第一轮 BO3第二场 6.2
2018/06/03 DOTA
[19:54]夜魇凡尔赛茶话会 第一期02:看图识人
2021/03/11 DOTA
python多线程threading.Lock锁用法实例
2014/11/01 Python
Python实现字符串格式化输出的方法详解
2017/09/20 Python
python中字符串比较使用is、==和cmp()总结
2018/03/18 Python
Python使用Opencv实现边缘检测以及轮廓检测的实现
2020/12/31 Python
Merchant 1948澳大利亚:新西兰领先的鞋类和靴子供应商
2018/03/24 全球购物
数百万免费的图形资源:Freepik
2020/09/21 全球购物
全球最大运动品牌的男装、女装和童装官方库存商:A&A Sports
2021/01/17 全球购物
MyBag中文网:英国著名的时尚包袋电商零售网站
2020/07/31 全球购物
写出SQL四条最基本的数据操作语句(DML)
2012/12/12 面试题
行政总监岗位职责
2013/12/05 职场文书
优秀班干部事迹材料
2014/01/26 职场文书
环保志愿者活动总结
2014/06/27 职场文书
2015年幼儿教师个人工作总结
2015/05/20 职场文书
解决pycharm安装scrapy DLL load failed:找不到指定的程序的问题
2021/06/08 Python
关于@OnetoMany关系映射的排序问题,使用注解@OrderBy
2021/12/06 Java/Android