这个系列保持开坑不埋的状态已经过去三个月了,而在这几个月中我才算第一次认真地深入理解js。虽然期间笔记是记了不少,但写博文又不应是简单的复制粘贴,还是得保证有讨论价值、有干货的。而我面对的现实是:一来基础差导致识别和捞出有讨论价值的干货得自身功夫练到一定阶段,二来又因为记的杂乱且缺乏日常整理,整理一下就是拖一下,再加上开学前后各种杂事层出不穷,所以这坑就一直留着。
但填坑是必须的,在深入学习的过程中,我意识到的最重要一点是:不能再摊大饼式地没总结就向前跑了,学习得是个分阶段上升的过程,而每个阶段又是理论和实践的交替往复,这样才有动力和能力去朝技术之巅进发。所以今天我就来总结一下学习js中一些探究过的点,与大家分享:
script标签的async、defer属性
script标签除了有常见的type
属性外,还有两个比较实用的属性async
、defer
。我们在需要使用无阻塞下载、执行的外部脚本、实现性能优化时往往要用到这两个属性。他们具体的作用如下:
使用
async="async"
:异步下载外部脚本,脚本一下载完就执行,在先于load
事件任何地方都可能执行不使用
async
且defer="defer"
:异步下载外部脚本,脚本将在页面完成解析时顺序执行,理论上先于DOMContentLoad
事件执行不使用这两属性:下载外部脚本时会阻塞,脚本一下载完就执行
就这个内容,我写了个小demo,分析其运行结果,就执行顺序来讲,带async
、defer
属性的脚本较慢执行,不管原来script标签的使用顺序,确实异步了;而用defer属性或者两者都没使用的脚本内部也确实是按顺序执行的。至于下载脚本的过程,我暂时没想到测试方法,只能先搁一边了。
当然,就加载和性能优化来讲,这两个属性只是一方面而已,若有兴趣可看这篇较详细的介绍。
parseInt()和parseFloat()的一些特性
由于Number()
函数在进行字符串向Number类型转换时存在一些坑(比如Number('')
返回的是0),parseInt()
和parseFloat()
这两个函数是专门用来替代Number()
函数实现字符串向Number类型的转换的。两者间对比的一些要点:
要点 | parseInt() | parseFloat() |
---|---|---|
1.解析过程 | 忽略串前空格符,找到第一个非空格字符 | 忽略串前空格符,找到第一个非空格字符 |
--- | ↓数字或负号? | ↓数字或负号? |
--- | Y:解析至字符串结束或遇到非数字字符,返回整数; N:返回NaN |
Y:解析至字符串结束或遇到无效浮点字符(多个小数点或非数字),可解析为整数则返回整数返回整数,否则返回浮点数; N:返回NaN |
2.进制识别与转换 | 支持(8进制在ES5中会忽略前导0而变为十进制) | 不支持(忽略所有前导0,十六进制数被识别为0) |
3.采用第二参数指定基数 | 有(指定基数后原串不加数制前缀也可顺利转换) | 没有,只支持十进制 |
这里面顺便注意下js的一个坑---parseInt(0.000001)
返回的是0,但parseInt(0.0000001)
却会返回1。
其实这个坑不在于parseInt()
本身,而在于js一个将小于1e-6的数自动转为科学计数法表示的规定,比如0.0000001会自动表示为1e-7。
可以看到,parseInt(0.0000001)
的过程涉及两次转换,首先参数为Number类型将调用toString()
变为字符串,0.000001会变成'1e-7'。其次便是将字符串转化为数字,根据前面提到的parseInt()的解析过程,自然就出现了那个返回1的坑爹结果。
抠一下NaN和Infinity的细节
NaN
是js里一个奇特的存在,有着既是Number类型却并不是一个数、自己不等于自己等奇葩特点。如果不清楚什么情况下NaN
会出现,冷不防就会对执行结果判断错误。其实NaN
的出现还是有点规律的,如下所示:
除了
!NaN
外的其他含有NaN
的操作无法得出结果的运算:
Infinity*0
、0/0
、Infinity-Infinity
、Infinity
除以任何数···其他类型转换为数字时失败,如
Number('abc')
除了NaN
,Infinity
也是个特殊的Number类型,当它和0纠葛在一起乘除取余时,结果表面看起来也有点迷:
其实这里面相乘的最容易理解,而有一点基本的极限知识都知道1/0==Infinity
、1/Infinity==0
,把除看成乘也容易理解了。相除的理解、剩下的取余也就自然明了。
innerText和textContent
innerText
并不是一个标准的属性,textContent
才是,所以火狐长久以来都不支持innerText
,同时IE<9也不支持textContent
。当然这两者也不是完全相同,区别在于读取属性时,innerText
不返回隐藏元素的文本,而textContent
返回所有文本(如元素文本里的换行符)。
至于选用哪个的问题,我觉得不要求兼容低版本IE的话,就直接用textContent
,如果不希望获得隐藏的文本,则后期再根据获取的字符串进行修改。
关于原生的Date()
Date()类型的使用看起来简单,比如创建Date对象:var d = new Date(年, 月, 日, 时, 分, 秒, 毫秒)/(时间戳)/(标准时间格式字符串);
但真要细究起来其内部的细碎之处也是叫人蛋疼,就上面三种传参方法,有这些区别:
时间参数:各浏览器都以当前时区返回日期对象,此处月份范围用整数表示是0~11
时间戳:各浏览器都以0时区返回日期对象
标准时间格式字符串:
RFC2822时间字符串:"YYYY+:MMM:DD+ HH+:MM+:SS+"+"Z或±HH:MM","YYYY/MM/DD HH:MM:SS"+"Z或±HH:MM" ,没加Z(零时区)或时区标志时各浏览器以当前时区返回日期对象
ISO 8601时间字符串:"YYYY-MM-DDTHH:MM:SS.mmm"+"Z或±HH:MM",chrome传参宽松而FF和IE严格按顺序和大小写,chrome会全部以0时区返回日期对象而FF和IE在加了HH:MM:SS后以按当前时区返回日期对象
我认为一味死抠没多少营养的细枝末节就是在浪费时间、降低效率,而看到这样一个创建对象的操作就包含这么多琐碎的东西,再死抠下去也是蛮无聊的,但还好已经有人写了个关于Date冷知识的全面总结了,我就不重复在这上面劳神费力了。
其他
在FF和chrome下使用
firstChild
,lastChild
,nextSibling
,previousSibling
四个属性时,会把标签之间的空格当成文本节点影响节点的获取,而在IE9以下的浏览器中却可正常获取。还是那句话,既然IE9之后大家都情况统一了,以后就不用考虑这点小兼容,全都乖乖用firstElementChild
,lastElementChild
,nextElementSibling
,previousElementSibling
这几个可靠的替代吧将数组转化为字符串时可用
join()
方法代替toString()
,因为这样写可以自定义分隔符getElementById()
只能通过document
调用,而不能通过其他DOM节点对象
一点感想
这次“重新”投入js学习,先是在暑假的开发中找教程从头看起,辅以一些小实践,也算让自己一直单薄许久的js知识有了些飞跃;但如果说以前我是站在js门外观望、走马观花,那现在也只是一只脚刚伸进门槛而已,在这个行业剧烈变换的今天,在node、angular、react等正式风生水起时,我既是为身处时代洪流感到兴奋,又不免感慨任重道远。参照别人的学习之路,再考虑自己的实际,接下来要做的还有许多。而现在大学过了一半了,出了这校门,大段的、连续的用来学习和自我提升的日子怕也是很难再有了吧;那么大三应是铸造坚实基础、或者说让自己跨进“专业人士”行列的重要阶段了,前路漫漫,待我渡之。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。