写出更好的JavaScript程序之undefined篇(中)


Posted in Javascript onNovember 23, 2009

写在前面的依然是消歧义声明:本文中JavaScript是指一般意义上的JavaScript,并不只限定“自称是JavaScript”的运行环境;“全局变量”和“全局对象的属性”是指同样的东西,只是因为要配合上下文才用了不同的说法,正文中我就不再另外解释了;“声明”指通过“var”语句声明变量和/或对函数及其签名的定义;“变量”指通过“var”语句声明过或者在函数体中试图访问的命名参数;“undefined”指名为“undefined”的值(全局或本地变量),而“未定义”指type(...) == “undefined”的概念值;“output”是向我们显示传入参数的函数,其实就是“alert”的同类。

首先介绍的是和void(0)具有异曲同工之妙的一种办法,我们知道在JavaScript中尝试访问任何一个“没有返回值”的函数的执行结果,都会得到“未定义”这个概念值,所以我们可以这样做:
myVar = function(){}();
这个方法的原理是创建一个空函数,并且获取其(根本不存在的)返回值。很明显,我们会得到“未定义”这个概念值,这个原理是和void(0)一样的。
需要特别注意的是,只有当function关键字不在语句之首的时候,才可以使用这种调用方式;如果需要直接调用一个匿名函数,应该这样做:

(function(){
// code here
})();
假如我们不想污染全局作用域,我们就可以用这种方式来创造一个闭包——很多现有的JavaScript库就是这样做的。
这种办法是在不了解void(0)的执行效果的情况下诞生的,既然我们知道void(0),也就不需要这种办法了。

第二种不常见的办法是访问window.undefined,就像下边这样:
output(myVar === window.undefined);
myVar = window.undefined;
这种办法的原理是:
如果JavaScript的运行环境预定义了undefined这一值,window.undefined就可以直接访问到;
如果没有预先定义undefined这一值,window.undefined就会返回“未定义”这一概念值——还是我们想要的东西。
访问形式从“全局变量”变成“属性”以后,脚本引擎就不会认为这是一个意外操作了,因此代码可以正确执行。

然而这种办法还是存在不足:
undefined在所有的JavaScript引擎中都不是保留字,也就是说它是可以被污染的,这会影响我们的程序的运行效果;
直接访问全局对象的属性效率是很差的,应该避免这么做。

因此,接下来就要介绍我所见过的最为有趣的办法——在本地声明undefined变量!
它的做法是这样的:
function myFunc(){
var undefined;
// some code here
output(myVar === undefined);
myVar = undefined;
}
说到这里我要提一下,有的人对“早期的浏览器上没有undefined”这一说法有不同的理解,认为上面这样的做法是行不通的。
而我认为这种观点是不对的,在我的印象中(大约是2003年),IE5虽然没有预定义undefined,但并不影响我们的不指派声明。
不过毕竟是很多年前的事情,记忆模糊,为了避免想当然造成的错误,我特地装了Windows 98来实验一下:
写出更好的JavaScript程序之undefined篇(中)
写出更好的JavaScript程序之undefined篇(中)

上面两幅是用了QQ屏幕截取 ,不知道为什么变成了JPG,下边这幅是用OneNote截取的。

写出更好的JavaScript程序之undefined篇(中)

由此可以得出,为这样不指派声明undefined变量担忧是多余的。
前一篇解释过,在JavaScript中,如果尝试读取一个没有预定义也未声明过的变量,会引发一个“不存在(未定义)”异常,因此在早期的浏览器上如果直接访问undefined的操作可能会失败。
这种(引发异常的)现象可能是为了方便排除故障而有意设计的;而对于声明过的变量,即使是未经赋值,也不会在读取的时候引发异常——经过声明就表示开发人员确定有“这个东西”。

上面这种在函数作用域内声明本地变量undefined的做法,既解决了引用未声明变量会引发异常的问题,又避免了受全局变量污染的影响,还取代了void(0)这种乍看之下意味不明的小把戏,不仅没有造成难以觉察的拼写错误的隐患,还能提高运算效率——真是一举N得的妙招!
所以了解了这么多之后就发现,最后介绍的这种办法实在是居家旅行、杀人灭口的首选
如果有人问:“undefined应该怎么用?”我们现在就可以回答:就这么用!

终于到了结尾,有的人可能忍不住要问了:为什么在这个系列中我的代码示例都用三个等号的“严格相等”来比较?两个等号的普通的“相等”有什么问题吗?
这就是这个系列的下篇要讲解的内容:undefined及其各种等价形态的适用场合。

Javascript 相关文章推荐
Javascript 获取LI里的内容
Dec 17 Javascript
javascript 客户端验证上传图片的大小(兼容IE和火狐)
Aug 15 Javascript
JS的replace方法介绍
Oct 20 Javascript
浅谈重写window对象的方法
Dec 29 Javascript
jQuery EasyUI 菜单与按钮之创建简单的菜单和链接按钮
Nov 18 Javascript
jQuery插件echarts实现的单折线图效果示例【附demo源码下载】
Mar 04 Javascript
backbone简介_动力节点Java学院整理
Jul 14 Javascript
web前端开发中常见的多列布局解决方案整理(一定要看)
Oct 15 Javascript
取消Bootstrap的dropdown-menu点击默认关闭事件方法
Aug 10 Javascript
JavaScript设计模式之装饰者模式实例详解
Jan 17 Javascript
微信小程序开发(二):页面跳转并传参操作示例
Jun 01 Javascript
vue keep-alive实现多组件嵌套中个别组件存活不销毁的操作
Oct 30 Javascript
通过身份证号得到出生日期和性别的js代码
Nov 23 #Javascript
javascript 在网页中的运用(asp.net)
Nov 23 #Javascript
javascript DOM编程实例(智播客学习)
Nov 23 #Javascript
传智播客学习之java 反射
Nov 22 #Javascript
Javascript 刷新全集常用代码
Nov 22 #Javascript
写出更好的JavaScript之undefined篇(上)
Nov 22 #Javascript
COM中获取JavaScript数组大小的代码
Nov 22 #Javascript
You might like
php实现简易聊天室应用代码
2015/09/23 PHP
Zend Framework教程之响应对象的封装Zend_Controller_Response实例详解
2016/03/07 PHP
yii2中dropDownList实现二级和三级联动写法
2017/04/26 PHP
thinkphp5.1 框架导入/导出excel文件操作示例
2020/05/25 PHP
[原创]js获取数组任意个不重复的随机数组元素
2010/03/15 Javascript
基于jquery用于查询操作的实现代码
2010/05/10 Javascript
asp.net+jquery滚动滚动条加载数据的下拉控件
2010/06/25 Javascript
jQuery实现下拉框选择图片功能实例
2015/08/08 Javascript
Javascript中神奇的this
2016/01/20 Javascript
jquery分隔Url的param方法(推荐)
2016/05/25 Javascript
JS实现点击网页判断是否安装app并打开否则跳转app store
2016/11/18 Javascript
jquery实现图片放大点击切换
2017/06/06 jQuery
详解webpack loader和plugin编写
2018/10/12 Javascript
js中async函数结合promise的小案例浅析
2019/04/14 Javascript
[26:52]LGD vs EG 2018国际邀请赛小组赛BO2 第一场 8.17
2018/08/18 DOTA
Python基于socket模块实现UDP通信功能示例
2018/04/10 Python
pytorch构建网络模型的4种方法
2018/04/13 Python
Python绘制3D图形
2018/05/03 Python
解决Django migrate No changes detected 不能创建表的问题
2018/05/27 Python
Django框架模板注入操作示例【变量传递到模板】
2018/12/19 Python
3种python调用其他脚本的方法
2020/01/06 Python
Python+redis通过限流保护高并发系统
2020/04/15 Python
phpquery中文手册
2021/03/18 PHP
YOINS官网:时尚女装网上购物
2017/03/17 全球购物
用C或者C++语言实现SOCKET通信
2015/02/24 面试题
30岁生日感言
2014/01/25 职场文书
企业承诺书怎么写
2014/05/24 职场文书
生产助理岗位职责
2014/06/18 职场文书
企业贷款委托书格式
2014/09/12 职场文书
村当支部个人对照检查材料思想汇报
2014/10/06 职场文书
敬业奉献模范事迹材料
2014/12/24 职场文书
大学生个人简历自我评价
2015/03/11 职场文书
独生子女证明范本
2015/06/19 职场文书
复活读书笔记
2015/06/29 职场文书
pytorch 权重weight 与 梯度grad 可视化操作
2021/06/05 Python
Python并发编程实例教程之线程的玩法
2021/06/20 Python