HTML5自十多年前(2010年前后)被推举以来,逐渐大放异彩,尽管过去十年是属于Native APP的高光时刻,但HTML5的一些新特性和功能还是带来了大量的新网络/网页应用,尤其是在JavaScript的加持下,网页应用有极其令人着迷的便利与强大。
JavaScipt是网页应用默认编程语言,让人又爱又恨。
笔者曾经在《中国计算机学会通讯》上刊发了一篇看法文章《JavaScript或成主导的编程语言》( https://dl.ccf.org.cn/institu... ),其后两个开源项目 GTAjax ( https://ufqi.com/dev/gtajax )和 Hanjst ( https://ufqi.com/dev/hanjst/H... )又分别是使用JavaScript做了实现,甚至 Base62x( https://ufqi.com/dev/base62x/ ) 的编解码方法,都有JavaScript语言版本,可谓是JavaScript的重度用户、开发者。
即便如此“资深”,仍常常觉得JavaScript用起来让人不那么放心,为了写出更可靠的代码,我们甚至在JavaScript中显示地声明用严格检查模式: use strict.
即便如此“谨慎”,我们也会遇到 object/variable is null or undefined 的异常抛出,使得程序异常终止,为用户带来了很不好的体验。随着我们在 UfqiWork/有福工坊( https://ufqi.com/work ) 的开发推进,我们尝试寻找一种检测 JavaScript 变量或者对象是否null 或 undefined方法的努力,有了新收获,兹分享如下。
从JavaScript本身来说,要检测某个对象或变量是否为null/undefined,主要有两个工具可用: typeof 操作符 和 window.hasOwnProperty 方法。我们所创制的方法, 代码1,也是基于这两个基本操作。
//- _isDefined
//- @param: $var, to be tested;
//- @param: global_or_local: ‘global|local’, optional
//- return true | false
//- usage: test whether a global variable($var): _isDefined(“$var”) , _isDefined($var)
//- test a variable($var) declared nearby/locally: _isDefined($var) , _isDefined(“$var”, “local”)
function _isDefined($var, global_or_local){
var isDef = false;
if($var != null){
var myTp = typeof $var;
if(myTp == ‘string’){
if(window.hasOwnProperty($var)){
isDef = true;
}
else if(global_or_local != null && global_or_local == ‘local’){
isDef = true;
}
else{
//- @todo
}
}
else if(myTp != ‘undefined’){
isDef = true;
}
}
return isDef;
}
这些代码已经部署在 Hanjst/汉吉斯特, UfqiWork/有福工坊 相关模块中,经实测,运行良好,符合预期。
在编制这些代码之前,我们也曾经在多个应用中写了大量的检测某个JavaScript是否为null/undefined,无一例外地都是使用 typeof 或者 window.hasOwnProperty方法,甚至再带着对 null和 empty的判断。代码显得异常繁琐和臃肿。相信此后,这些代码将陆续得到简化和修正,新写的代码也将引入该功能 _isDefined .
在编制这些代码之前,我们也在网络上进行了 code review,翻阅了大量针对此问题的解决思路和办法,可能面对不同运行时环境,给出的解决方法也各个不同,实际上并没有一种方法可以通用到“放之四海而皆准”。
比如最接近本方法的一个尝试是定义一个 isDefined2, 代码2,然后在方法体内使用 typeof 操作符判断传入的 $var 是否 null/undefined , 以此来进行判断变量或者对象 $var 是否为 null/undefined .
//- _isDefined2, WRONG!
//- @param: $var, to be tested
//- return true | false
function _isDefined2($var){
var isDef = false;
if(typeof $var != ‘undefined’){
isDef = true;
}
return isDef;
}
这段代码通常情况下,能够进行运行,并对一些变量实现null/undefined的探测。然而这个情况只局限在本地变量或者当前已经声明的变量,如果待探测的变量 $var 没有在 _isDefined2 调用之前被声明,则调用探测语句 _isDedined2($var) 本身就会报错说 $var is null/undefined .
问题进一步地被延申到 JavaScript的函数方法调用的参数传递是pass-by-value传值,还是 pass-by-reference传引用。通常情况下,JavaScript的方法调用都是 pass-by-value, 所以在执行语句 _isDefined($var) 时,先要对 $var 进行取值操作,而 $var 如果本身 undefined 时,悲剧错误就产生了,检测是否为 null/undefined 之前已经发生了 undefined .
当我们判断了 $var 为String类型的数据对象时,同时引发了另外一个问题,就是当某一个数据变量或对象其本身就是字符串时,如果其本身是一个本地变量,而String类型会被视为检测全局变量,这里就会发生异常错误,把本该返回本地变量为 true的结果,错误地解释为全局变量为 false。因此需要进一步地对方法本身做修正,使之能够兼容本地变量、String类型,改进的做法是针对 _isDefined 引入第二个参数,显示地告诉程序,当前虽然引入了 String类型的变量,但不是默认检测全局变量,而是要检测本地变量。
进一步地修正这个问题,我们创制了样例代码1. 可以兼容全局变量和本地变量,不管$var 是否被什么,都能够进行检测。只是,在调用的时候需要区分,待检测的变量或者对象是全局变量或者是局部变量:
如果是全局变量,调用方式是: _isDefined(“$var”) , _isDefined($var)
如果是局部变量,调用方法是: _isDefined($var, ‘local’) , _isDefined(“$var”, ‘local’)
变量 $var 在被检测之前,我们能够知道它是全局变量或者局部变量吗?
答案应该是明确的。
测试样例:
var a;
console.log(“UfqiWork/Hanjst: a:”+_isDefined(a));
var b = null;
console.log(“UfqiWork/Hanjst: b:”+_isDefined(b));
var c = 0;
console.log(“UfqiWork/Hanjst: c:”+_isDefined(c));
console.log(“UfqiWork/Hanjst: global-c:”+_isDefined(“c”));
var dd = “d_string”;
console.log(“UfqiWork/Hanjst: local-dd:”+_isDefined(dd, ‘local’));
console.log(“UfqiWork/Hanjst: global-dd:”+_isDefined(dd));
console.log(“UfqiWork/Hanjst: global-dd:”+_isDefined(“dd”));
console.log(“UfqiWork/Hanjst: local-dd:”+_isDefined(“dd”, ‘local’));
预期输出:
UfqiWork/Hanjst: a:false
UfqiWork/Hanjst: b:false
UfqiWork/Hanjst: c:true
UfqiWork/Hanjst: global-c:false
UfqiWork/Hanjst: local-dd:true
UfqiWork/Hanjst: global-dd:false
UfqiWork/Hanjst: global-dd:false
UfqiWork/Hanjst: local-dd:true
Hanjst
Hanjst 汉吉斯特 Logo
🙋Hanjst汉吉斯特 是一种基于JavaScript的模板语言及模版解析引擎,她运行在客户端或服务器端。
🙋Hanjst汉吉斯特 能够表述逻辑控制,能够实现与服务器端模版语言相同的强大功能。
Hanjst当完全在客户端解析时,节省服务器端计算资源;
Hanjst模板语言独立,不与服务器端资源做任何绑定;
纯粹的MVC,层间数据用JSON格式传递;
常见模板语言功能全支持,附带复杂而强大的JavaScript编程能力;
无学习成本,直接使用JavaScript书写模板语言;
….
Hanjst is a JavaScript-based templating language and parsing engine that runs on both the client-side and/or server-side.
Hanjst can express logical controls and achieve the same functionalities as the server-side templating languages.
Hanjst’s Run-time in client-side, reduce computing render in server-side;
Hanjst is Language-independent, not-bound with back-end scripts or languages;
Totally-isolated between MVC, data transfer with JSON;
Full-support template tags with built-in logic and customized JavaScript functions;
No more tags languages to be learned, just JavaScript;
….
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。