javascript语言中的毒瘤(上)

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

未完待续。。。。。

时间: 01-10

javascript语言中的毒瘤(上)的相关文章

javascript语言中的毒瘤(下)

javascript语言中的毒瘤(下) 伪数组 Js中没有正真意义上的数组:这使得数组的使用非常容易,你不必给他们设置维度:而且永远不会产生越界错误:但它的性能相比正真的数组就糟糕了: Typeof 运算符不能辨别数组和对象,要判断一个值是否为数组,你还需要检查它的construtor属性:(也可以使用instanceof) function isArr(my_value) { if(my_value&& typeof my_value === 'object' && my

JavaScript 语言中的 this

JavaScript 语言中的 this 由于其运行期绑定的特性,JavaScript 中的 this 含义要丰富得多,它可以是全局对象.当前对象或者任意对象,这完全取决于函数的调用方式.JavaScript 中函数的调用有以下几种方式:作为对象方法调用,作为函数调用,作为构造函数调用,和使用 apply 或 call 调用.下面我们将按照调用方式的不同,分别讨论 this 的含义. 作为对象方法调用 在 JavaScript 中,函数也是对象,因此函数可以作为一个对象的属性,此时该函数被称为该

JavaScript语言标识符和保留字

任何一种计算机语言都离不开标识符和保留字,下面我们将详细介绍JavaScript标识符和关键字.标识符      标识符就是给变量.函数和对象等指定的名字.构成标识符的字母是有一定的规范,JavaScript语言中标识符的命名规则:区分大小写,Myname与myname是两个不同的标识符.      标识符首字符可以是以下划线(_).美元符($)或者字母开始,不能是数字.      标识符中其它字符可以是下划线(_).美元符($).字母或数字组成的. 例如,identifier,userName

《javascript语言精粹》读书笔记一

前言 这是一本老道(douglas crockford)写的关于js的经典书籍,这本书的英文名称叫做<javascript:the good parts>,它诠释的是js这门语言的精彩部分,可以说他将js这门语言中最精华和有趣的部分都展现在大家面前了. 由于最近比较忙碌,在抽空搭建起blog了以后,直到现在才真正的提起劲头来准备真真的写点什么,其实也是为了给自己一个督促和鞭策,同时把在书中看到的觉得很棒的部分记录下来. 第二章 语法 本章介绍js的语法,这里没有什么特别的地方,语法是一门语言的

JavaScript语言核心(一)-- prototype

类似C++强类型的静态语言中,类型 决定了 值具备的属性及method.设计好的类型在running的过程中,无法变更 JavaScript弱类型 动态语言中没有 class 即 语言中是"没有类型",对象的类型 是由运行过程中的值决定. 本类型不具备的方法借用其他类型的方法 扩展其他类型 字符串类型 不具备join方法,但可以借用 其他类型 Array中的方法 let str = 'foo'; var res = Array.prototype.join.call(str,'-');

JavaScript语法中分号使用的细节

关于JavaScript中可选分号的问题有几个细节要注意: 一般来说,JavaScript和其他语言一样都是使用分号,将语句隔开,但在JavaScript中,如果语句各自独立一行,有时也可以省略分号的 细节1: 如果当前语句和随后的非空格字符不能当成一整体来解析的话,JavaScript就在当前语句行结束处自动填补分号 var a a = 3 console.log(a); JavaScript将上述代码解析为: var a; a=3; console.log(a); 第一行代码 var a自动

javascript语言精粹----笔记【转载】

javascript语言精粹----笔记 1.6种值会为假(==false),分别是false,null,undefined,' ',0,NaN 2.typeof有6种值,分别是'number','string','boolean','undefined','function','object';其中typeof(null),结果是'object' 3.number类型总是64位浮点数,两个整数相除也可能出现非整数结果 4.如果第一个运算数的值为假,那么运算符&&产生它的第一个运算数的值.

稍微谈一下 javascript 开发中的 MVC 模式

随着前台开发日益受到重视,客户端代码比重日益增加的今天,如何在javascript开发里应用MVC模式,这个问题似乎会一直被提到,所以偶在这里粗略的谈一下自己的看法吧. MVC模式的基本理念,是通过把一个application封装成model, view和controller三个部分达到降低耦合,简化开发的目的.这么说很空洞,大家可以实际看个例子: 1<select id="selAnimal"> 2    <option value="cat"&

javascript学习中自己对作用域和作用域链理解

在javascript学习中作用域和作用域链还是相对难理解些,下面我关于javascript作用域和作用域链做一下详细介绍,给各位初学者答疑解惑. 首先我们介绍一下什么是作用域?  从字面上理解就是起作用的区域.   作用域主要有两种作用域:      1.块级作用域(js 不支持):主要用于C系列语言中,例如:Java Object-c/Swift(苹果开发语言).C++/C#.在此不做过多说明.      2.词法作用域  一个变量的作用范围,在代码写出来的那一刻就定下来了,不会根据代码的运