我的NodeJs学习⼩结(⼀)
这第⼀篇就谈谈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、数组和对象不要混⽤
下⾯是错误代码的⽰例:
sort函数 jsvar 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+规范,⽹上有⼏种实现⽅式,可以参阅。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论