JS实例教程:当心JavaScript代码陷阱

下面这段代码,你知道有哪些错误吗:

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  document
name = 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 = 2
var 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;

简单质朴,往往是最好的。

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索变量
, 代码
, container
, config
, var
, undefined
Falsy
,以便于您获取更多的相关知识。

时间: 2024-08-01 17:59:14

JS实例教程:当心JavaScript代码陷阱的相关文章

js实例教程:JavaScript Events 事件使用方法

js实例教程:JavaScript Events 方法 事件的行动,可以检测到了JavaScript . 活动 通过使用JavaScript ,我们有能力创建动态网页.事件的行动,可以检测到了JavaScript . 每个要素在网页上有一定的事件可以触发JavaScript函数.例如,我们可以使用onClick事件的一个按钮的内容表明,一个函数将运行当使用者按下按钮.我们确定了事件中的HTML标记. 事件的例子: 点击鼠标 一个网页或图片加载 鼠标过热点网页上 选择一个输入框在一个HTML表单

Svg.js实例教程及使用手册详解(一)_javascript技巧

什么是SVG? SVG 指可伸缩矢量图形 (Scalable Vector Graphics) SVG 用来定义用于网络的基于矢量的图形 SVG 使用 XML 格式定义图形 SVG 图像在放大或改变尺寸的情况下其图形质量不会有所损失 SVG 是万维网联盟的标准 SVG 与诸如 DOM 和 XSL 之类的 W3C 标准是一个整体 简介: SVG.js是一个轻量级的JavaScript库,允许你轻松操作SVG和定义动画. SVG(Scalable Vector Graphics,可缩放矢量图形)是基

js异步加载Javascript代码示例详解

当我们在Javascript里需要用到jQuery但又无法判断是否加载过时,可以通过下面的方法来自动判断并加载jQuery,代码如下:  代码如下 复制代码 function getScript(url, success) {     var script = document.createElement('script');     script.src = url;     var head = document.getElementsByTagName('head')[0],     do

JS实例教程:制作图片放大特效

效果: 运行代码框<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="

CSS3实例教程:用CSS代码绘制新浪LOGO

文章简介:用CSS3绘制小新. 新浪有两个吉祥物,小新是女孩儿,小浪是男孩儿.现在流行用CSS3画点什么,我们SINA CDC的模特儿,必然是小新和小浪了. 熬一晚上做了个小新头,不完善,还有更像的空间.窍门就是琢磨出用各种圆形,相互迭加而制作出一个物体.先看看最终效果吧.个人认为,firefox在图型方面的表现是最好的,而safari和chrome虽然有毛边,但优势是支持CSS动画.各有所长.而IE,就当它是打酱油的吧. 这次使用到的CSS3属性包括: 圆角:-moz-border-radiu

JS实例教程:用6N±1法求素数

用6N±1法求素数任何一个自然数,总可以表示成为如下的形式之一:6N,6N+1,6N+2,6N+3,6N+4,6N+5 (N=0,1,2,-)显然,当N≥1时,6N,6N+2,6N+3,6N+4都不是素数,只有形如6N+1和6N+5的自然数有可能是素数.所以,除了2和3之外,所有的素数都可以表示成6N±1的形式(N为自然数).根据上述分析,我们可以构造另一面筛子,只对形如6 N±1的自然数进行筛选,这样就可以大大减少筛选的次数,从而进一步提高程序的运行效率和速度. 以下代码需要自然数大于10fu

JavaScript For 语句使用实例教程

JavaScript For 语句使用实例教程 在JavaScript中循环使用执行相同的代码块指定的次数或在指定的条件是真实的. 范例 For循环 如何写一环.使用的闭环运行相同的代码块指定的次数. 通过循环的HTML标题 如何使用的循环回路通过不同的HTML标题. JavaScript的For循环 往往当你写代码,你想同样的代码块运行一遍又一遍连胜.反而增加了几乎相等线脚本,我们可以用循环来执行这样的任务. 在JavaScript中有两种不同类型的循环: 为-循环通过代码块指定的次数 而-循

JavaScript代码格式化工具(JS代码分析必备)

推广等的控制广告显示的JS文件及生成的广告单元的源文件中的JavaScript代码都是经过JS压缩器以及混淆器处理后的.以达到减小这些文件的大小的目的. 当我们需要分析这些文件的时候就需要格式化javascript代码的工具,使之方便阅读. 在这里我给大家介绍的就是Javascript Code Improver 一个免费的工具.他很简单,只有格式化代码这一个功能,不过,足够用了.支持中英文界面切换. 下载:Javascript Code Improver JavaScript Code Imp

Windows 8实例教程:布局控制

与传统应用类似,Windows store应用允许开发人员通过布局控件管理应用UI. 本篇将讨论Windows8布局设计控制. Windows 8布局控件 在Windows Store应用设计中,布局控件是控制对象位置和尺寸的,由于Windows Store应用不仅仅面向桌面操作系统,而且还需要适应移动设备的部署,所以在设计时,往往需要考虑到不同的分辨率或者硬件屏幕尺寸标准下应用布局的适配性,最大程度的保持设计灵活性是应用设计原则重要环节之一.根据功能性不同,Windows 8为开发人员提供丰富