javascript语言中的毒瘤(上)
最近翻了《javascript语言精髓》,对js有了更进一步的了解,特别是js的糟糕特性,下面,结合书中的要点,给大家分享一下js的几个糟糕特性。
全局变量
全局变量实在所有作用域均可以访问的变量,在一些小型项目中全局变量给我们获取和使用函数,数据等提供了灵活,便捷;但是随着程序的越来越庞大,全局变量就变得越来越难维护;(因为一个变量可能会在很多地方被修改,还有可能被覆盖),一旦出现问题也很难定位和调试。
Js的问题不仅在于它容许使用全局变量,而且在于它依赖全局变量,js中没有链接器,所有编译单元都载入一个公共的全局对象中;
一般有三种方式定义使用全局变量:
1,在任何一个函数之外,定义,如:var name = “jxj”;
2,直接给全局对象,添加一个属性,如:window.job = “FED”;
3,直接使用未经声明的变量,这种被称为隐式全局变量,如:name =”jxj”;
鉴于全局变量的问题,一般建议一下两种方式避免使用全局变量,以及全局污染:
1,创建命名空间,如:var my Sapce ={}
mySpace.login = {“modelId”:”login”,pws:”***”};
mySpace.log = {“modelId”:”log”,content:”***”};
2,使用闭包,将变量封装在自己的作用域内,避免污染全局
作用域
Js的语法来源于C,一个代码块会创建一个作用域;代码快中声明的变量在其外部是不可见的;js采用了这种块语法,却没有提供块级作用域;导致代码块中声明的变量在包含此代码块的函数的任何位置都是可见的;
在大多数的语言中,一般来讲,声明变量的最好地方实在第一次使用的地方;但在js这反而不好,因为他没有块级作用域;因此建议在每个函数开头部分声明所有变量。
自动插入分号
Js有一个自动修复机制,他试图通过自动插入分号的方式来,修复缺损的程序;但是,千万不能指望,他可能会掩盖更为严重的错误。
有时候,他会不合时宜的插入分号;如果一个return 语句返回一个值,这个值表达式的开始部分必须和return位于同一行:
return
{
Status:true
} ;
这看起来是要返回一个包含status成员元素的对象;但是自动插入分号会让它变成返回undefined,自动插入分号导致程序被误解,却没有任何提示,导致出了问题难于定位;
避免该问题的方法就是,把“{ ”放在上一行的尾部而不是下一行的开头,如:
return {
status:true
};
保留字
Js中的保留字不能被用来命名变量或参数;(各个浏览器在对保留字的使用限制上不同版本有不同的处理,根据测试object = {case:value};在目前主流浏览器版本中是合法的;但是在老版中可能有问题);但是当保留字被当做对象字面量的键值时,它们必须被引号括起来,它们不能被用在点表示法中,所以有时必须使用括号表示法。
所以最好的方式,就是不要使用保留字作为变量名。
parseInt
parseInt()是一个把字符串转换成证书的函数,他遇到非字符串会停止解析;所以,parseInt(“16 kg”),parseInt(“16”),parseInt(“16 tons”)产生的结果是相同;我们可能希望的是,解析错误时,不是仅仅停止解析,最好还能告诉我们出错了,但是它不会。
而且,如果该字符串第一个字符时“0”,那么该字符串会基于八进制而不是十进制求值;在八进制中8,9不是数字,所以parseInt(“08”),parseInt(“09”);都产生0作为结果;这个错误导致解析日期和时间时出现错误。
不过,parseInt()可以接受一个基数,作为参数,parseInt(“08”,10),就返回了8,所以建议加上这个技术参数。
加号“+”
+运算符可以用来加法运算或字符串连接,至于究竟如何执行,取决于参数的类型;如下:
var ss =" "+12;
ss;
" 12"
var dd =" jxj"+12;
dd;
" jxj12"
var cc =12+34;
46
这个复杂的行为是程序bug的常见来源,所以,使用+时,我们一定好考虑全面。
浮点数
二级制的浮点数不能正确的处理十进制的小数,因此0.1+0.2不等于0.3;这是js中最经常被报告的Bug,并且它是遵循二进制浮点算数标准二有意导致的结果;不过我们通过乘以100,等等进行转换,在除以100等,得到精确的结果;
NaN
NaN是IEEE754中定义的一个特殊的数量值,他表示不是一个数字,虽然下面表达式返回true:
typeof NaN ====”number”//true
该值一般出现在师徒把非数字形式的字符串转换为数字时,产生例如:
var aa = parseInt("aa");
aa;
NaN
一般typeof不能辨别数字和NaN,而且也不会等于它自己,所以,下面代码会令你吃惊:
NaN ===NaN;
false
NaN !==NaN;
true
js提供了一个isNaN函数,可以辨别数字和NaN,如下:
isNaN("12");
false
isNaN(NaN);
true
isNaN("JXJ");
true
isNaN(12);
false
当然判断一个值是否可用做数字的最佳方法是使用isFinite函数,因为它会筛选掉NaN和Infinity;
isFinite(12);
true
isFinite("12");
true
isFinite("jxj");
false
isFinite(NaN);
false
isFinite(Infinity);
false
不过遗憾的是,会试图把它的运算符转换成一个数字,所以也是不准确的;
下面定义了一个isNumber函数:
var isNumber =function (value) {returntypeof value ==="number" && isFinite(value);}
undefined
isNumber(12);
true
isNumber("12");
false
isNumber(NaN);
false
isNumber(Infinity);
false
isNumber("jxj");
false
未完待续。。。。。