可能被你忽略的 JavaScript 代码陷阱
作者:lifesinger 来源:岁月如歌 发布时间:2009-12-26 18:16:00
下面这段代码,你知道有哪些错误吗:
var g_bar = "bar";function foo(container, config) { var container = container || document, name = config.name || "无名氏", isLive = config.isLive || true; var g_bar = g_bar || ""; if(g_foo) { /* your code */ }}foo(document, {isLive: false});
请仔细思考后再往下阅读。
—- 帮助你思考的刷屏线 开始 —-
—- 帮助你思考的刷屏线 结束 —-
1. isLive = config.isLive || true
, 当传入的值有可能就是0, undefined, null, false, "", NaN
这六个 falsy 值时,用 || 来设定默认值不妥当。更保险的做法是:
isLive = "isLive" in config ? config.isLive : true;
如果是独立变量,可以采用:
someVar = typeof someVar !== "undefined" ? someVar : defaultValue;
注意:大部分情况下,用 || 已经够用,比如:
container = container || documentname = config.name || "无名氏"
一切皆权衡。
2. var g_bar = g_bar || ""
, 原意是取全局变量 g_bar 的值给内部变量 g_bar, 默认为空字符串。然而,实际情况等价为:
var g_bar;g_bar = g_bar || "";
很明显,|| 号左边的 g_bar 也是内部变量,并且为 undefined, 因此var g_bar = g_bar || ""
实际上是var g_bar = ""
, 没有满足代码的原始意图。
思考:代码中的var container = container || document
有无问题?为什么?
3. if(g_foo) { /* code */ }
, 这段代码在执行时会报错。我们都知道在 JS 里,变量不定义就可以用。但一定要清楚,未定义的变量,仅仅是可写,但不可读。比如:
g_foo = 2; // 等价 window.g_foo = 2var t = g_foo2; // 不等价为 var t = window.g_foo2, 会报错
具体原因可以参见 JavaScript 运行机制浅探:
未定义变量意味着在 scriptObject 的变量表中找不到,JS 引擎会沿着 scriptObject 的 upvalue 往上寻找,如果都没找到,对于写操作 i = 1; 最后就会等价为 window.i = 1; 给 window 对象新增了一个属性。对于读操作,如果一直追溯到全局执行环境的 scriptObject 上都找不到,就会产生运行期错误。
因此严谨的写法是:
if(window.g_foo) { /* your code */}
不要小看这些细微之处,有时会让人抓狂的。但这些细微之处又很容易被忽略或滥用。比如 YUI 2.8r4 里,有一个遗传了很久的 bug:
var NOTHING = [];// ....later: function(when, o, fn, data, periodic) { when = when || 0; o = o || {}; var m = fn, d = data, f, r; // ... if (d && !L.isArray(d)) { d = [data]; } f = function() { m.apply(o, d || NOTHING); }; // ...}
当你的调用代码类似Lang.later(delay[0], o, "show", index)
时,如果 index 不幸是 base-0 的,那么取 0 时,m.apply(o, d || NOTHING)
会让你得到“惊喜”。更妥的做法是类似 YUI3 中的修正:
// ...if (!L.isArray(d)) { d = [data];}?f = function() { m.apply(o, d);};//...
对于 || 和 && 的用法,很多 JS 书籍(无论中外),都用来片面强调 JS 的灵活性,包括 Douglas 的《JavaScript The Good Parts》中也存在误导。
最后,有感于 NCZ 今天写的 Writing Maintainable Code, 再举一例(和本文主题关系不明显,但的确又有关系,交给你去思考啰):
var isBoy = true;isBoy = typeof isGirl !== "undefined" ? !isGirl : true;
或者来个耍酷的代码:
var isBoy = true;(typeof isGirl !== "undefined") && (isBoy = !isGirl);
然而,以上两种写法,无论从代码长度还是性能上讲,都不如更直白的写法:
var isBoy = true;if(typeof isGirl !== "undefined") isBoy = !isGirl;
简单质朴,往往是最好的。
猜你喜欢
- 我们知道,任何数据库系统都无法避免崩溃的状况,即使你使用了Clustered,双机热备……仍然无
- 背景尽管到目前为止HTML4和XHTML1仍能够很好地满足我们的要求,但是它们仍然存在不足。为了满足用户丰富的基于Web应该程序的需要,达到
- 10月9日是国庆中秋黄金周后上班的第一天,当天近8亿人次逛淘宝,即淘宝网每分钟完成43.47万元的交易,创下国内网购单天交易最高纪录。从销售
- SQLSTATESQL SERVER 驱动程序错误描述 HY000所有绑定列都是只读的。必须是可升级的列,以使用 SQLSetPos 或 S
- asp正则表达式检测字符串是否是数字及字母。<% '函数:CheckString(strng) '
- 函数名:chk_Email()'返回值:布尔值(True为通过,False为未通过)'参数:email(需要判断的email
- SQL Server定位于中型的数据库应用,操作较Oracle和MySQL等要相对简便,SQL Server在处理海量数据的效率,后台开发的
- 1.查询高于平均价格的商品名称:SELECT item_name FROM ebsp.product_mark
- 我见朋友可以把数据库的记录显示到列表框里去,挺实用,也想做一个。怎么做啊?这简单,代码和说明如下:dblist.asp<html>
- 代码如下:function checkip(checkstring)'用正则判断IP是否合法 dim re1 set re1=new
- 此站:http://www.cbmland.com/ 的页面离开时的效果非常NB!佩服的很。一开始,我以为是用事件 onunload,试了一
- Asp定时执行操作、Asp定时读取数据库(网页定时操作详解)'----------------------版权信息---------
- 一组常用的弹出窗口用法,以下代码集合常用的弹出窗口用法。1、最基本的弹出窗口代码<SCRIPT LANGUAGE="
- 在讲这个问题之前让我们来先看一段代码: dim sql_injdata,SQL_inj,SQL_Get,SQL_Data,Sql_
- 方法一 <%dim total(7,3) total(1,0)="ASP之家"&n
- 本文介绍了随机提取N条记录的例子,通过Sql server与access数据库的代码比较让你更快的掌握。随机提取10条记录的例子:Sql s
- 似乎讨论分页的人很少,难道大家都沉迷于limit m,n?在有索引的情况下,limit m,n速度足够,可是在复杂条件搜索时,where s
- 当一张的数据达到几百万时,你查询一次所花的时间会变多,如果有联合查询的话,我想有可能会死在那儿了。分表的目的就在于此,减小数据库的负担,缩短
- 在 CodeBit.cn 的论坛中,有人问 Javascript 中如何截取小数位并实现四舍五入,这是一个很常用的 js 技术,帖子中也有网
- 前几天因为一个例外,数据库在没有做备份的情况下,直接删除了表记录。事后,又需要查询到删除的记录的内容。因此,在网上软件SS了半天,发现Log