欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

jacascript 需要注意的一些细节

程序员文章站 2024-02-28 14:18:16
...

函数自调的写法

自调函数的作用是构造一个函数级的变量作用域,常见的写法是:

(function)(){
    //code
}()

这样写可能被JS理解成一个函数调用。
其实我们可以这样写:

void function({
    //code
})

也可以用 !打头

在standardjs 日益流行的今天,忽略行尾分号成为了主流

检查一个变量是否为对象之前,首先判断它的值是否为null

毋庸置疑的,null不具备作为对象类型的基本特征,是原始类型。这是一个广为人知的JS的BUG,从JS诞生时就存在,而且从为被修复

所以,要判断一个变量的类型时,首先要判断它是否为null

if(someVal !== null && typeof someVal ==='object'){
    //someVal 是一个对象
}

做数值计算时,注意JS数值类型的精度

在JS里,所有的number原始值都是一个双精度浮点数,对应Java的double类型,对应标准IEEE754,小心它的精度问题

做整数处理时,注意数值的大小

JS最大可存储的安全整数(不存在精度问题)为9007199254740991(16位,Number.MAXSAFEINTEGER),注意比Java的Long类型最大整数92233720368547475807(19位)小几个数量级,所以有时JS的number类型是不能精确存储Java整数的(通常情况下不是问题)

问题通常处在前后端的数据传输上,数据库中的主键通常是一个自增长的长整数类型,有可能会超出JS的安全整数范围,这是请考虑使用字符串传输

做小数计算时,注意浮点数的精度问题

例如:

0.1 + 0.2 => 0.3000000000000004, 0.4 - 0.3 => 0.10000000000000003

将小数转化为字符串时,永远记得使用 toFixed 取小时点后若干位数字

0.1+0.2).toFixed(2) === '0.3';

比较小数相等时,切记不要直接使用 === ,而要使用相减取绝对值得方式(表示两数相差在一定范围内既认为他们相等)

0.1+0.2 === 0.3  //false
Math.abs(0.1+0.2-0.3) <= 1e-10  //true

NaN !== NaN

NaN之所以NB,因为它有一个独一无二的特性,那就是

NaN === NaN  //false
var a = NaN; a === a   //false

NaN 不等于他自己,你可以使用这个特性判断一个变量是否为NaN,一个变量如果不等于它自己,这个变量肯定是NaN。

还有一个方式是是引用Number.isNaN.注意,如果已知这个变量的类型时数字时,不要使用isNaN做判断,因为isNaN有个诡异的特性:他会先将判断的变量转化为数值类型

isNaN('abc') //true
isNaN('123') //false
isNaN('') //false
isNaN([]) //false
isNaN({}) //true

永远不要写 someVal === NaN

正确使用parseInt

首先parseInt接收两个参数,第一个参数为待parse的字符串(如果不是字符串会首先转换为字符串);第二个参数为使用的进制数。

如果不传第二个参数,则进制由第一个参数决定,什么意思呢?比如以0x开头的字符串,会被解析为16进制数。

我们知道以数字0开头的数字为8进制数(非严格模式),比如 011 === 9,0本身也是8进制数,那么问题来了,parseInt(‘011’)=?

答案是看浏览器。目前绝大多数浏览器都会作为10进制数解析,结果为11,但是还有一些老旧的浏览器以8进制数解析(例如IE8和一批老安卓的浏览器)

所以如果你非要用parseInt,

parseInt 使用规则一:请传入第二个参数
回到parseInt本身的含义。顾名思义这个函数是在parse,被parse的一定是个字符串,如果第一个参数不是字符串,那么会首先被转换为字符串。

parseInt(0.0000008)=?

String(0.0000000)=>’8e-10’

parseInt(‘8e-10’)=>8

parse使用规则二:永远不要使用parseInt给小数取整
建议对于数值转换一概使用强制转换函数Number,如果你JS用6了可以使用+(正号)
如果需要对某个数字取整,建议使用Math.tunc,如果你能确定数值在32位以内,可以使用x|0或者~~x等方式

jacascript 需要注意的一些细节

parseInt 的用处在于转换一些CSS里带单位的值:parseInt(‘10px’,10) => 10.但这里建议使用parseFloat,可以解析小数又没有进制问题。

除了用于比较null或者underfined,永远不要使用非严格相等 ==

绝不要简单的把非严格相等==理解为两者表示的数字一样,它有一套非常负责的转换规则:他会将%%转换为@@,然后把!!转换为**,如果%%是??类型,还会xx

'true' == true //false
'true' == false //false
[] == {} //false
[] == [] //false

关于非严格相等,只需要记住这个规则

null == null //true
undefined == undefined //true
null == undefined //true
undefined == null //true
x == null //false
x == undefined //false

简言之

x == null 

是最简单的判断x非null和undefined的方式,这就是 == 存在的唯一意义

日期处理

new Date(year,month,day)注意其参数的数值范围

由于可能的历史传承原因,JS内置对象Date的构造函数比较特殊

  1. 如果 year 是 0-99 之间,year 默认加 1900.比如 1 代表公元 1901 年,100 代表 100 公元 100 年。(你问 -1 是几?公元 1 年。。。)
  2. month 从 0 开始算,0 代表一月,1 代表二月,以此类推,12 代表下一年的 1 月(自动进位)

第二点容易出错,切记它是以 0 开始的数字。

这样得到的日期对象是本地时间(采用客户端时区)

new Date(dateString)注意浏览器时区问题以及浏览器兼容性

时常有些后端接口返回一个日期字符串的情况:

new Date('2018-01-01')  //2018/1/1 08:00:00 新版浏览器 IE11
new Date('2018-01-01')  //2018/1/1 00:00:00 某些旧版安卓浏览器
new Date('2018-01-01')  //'invalid Date' IE8(这个--)

可以看到,浏览器基本都是把日期字符串当做UTC时间处理的,而

new Date('2018/01/01')  //2018/1/1 00:00:00 包括IE8在内 其他所有浏览器

所以对于日期字符串,请注意字符串中是使用横杠还是斜杠。对于横杠可以考虑将 - 替换成 / ,或者补全完整的带时区的 ISO8061 字符串 。考虑到负数时区的时区问题,不推荐将小数清零的做法。

PS:将日期对象取当天 0 点为:

date.setHours(0,0,0,0)

去当前时间的 Unix 时间戳可以 new Date()
jacascript 需要注意的一些细节

补:慎用 || 填充默认值

这反而是JS老鸟更加容易犯的错误,给用户传入的对象填充默认值是很常见的行为,他们总是随手就写:

config.prop1 = config.prop1 || 233;
config.prop2 = config.prop2 || 'banbal'

expr1 || expre2 的意思是:如果 expr1 能转换成 true 则返回 expr1,否则返回expr2

expre1 || expre2 <=> Boolean(expre1)?expre1:expre2

哪些值不能转换为 true 呢?

  1. null
  2. undefined
  3. NaN
  4. 0!!!
  5. 空字符串 (”) !!!

如果用户指定了传入参数的值为 0 或者是空字符串的配置项,他的值就会被强制替换为默认值,然而实际上只有 Undefined 应该被认为是用户没有指定值(语义上可以这样理解:null表示 用户让你把这个位置空着;而undefined表示,用户没发表意见)

所以就是这样:

config.prop1 = config.prop1 !== undefined ? config.prop1 : 233;
config.prop2 = config.prop2 !== undefined ? config.prop2 : 'banbal'

可以搞一个全局函数简化这一操作。