javascript 语言精粹
数组
javascript中并没有真正的数组,数组本质上也是对象
请看下面的例子:
1 | var arr = [1,2,3,4,5,6] |
由运行的结果可以看出给数组添加了一个abc属性,尽管字面上的长度有所增加,但是数组的实际长度并没有改变!
1 | typeof [] // 'object' |
所以为了区分数组和对象我们应该可以采用以下的函数:
1 | let isArray = value => !!value && typeof value === 'object' && value.constructor === Array |
正则表达式
分组
观察以下匹配url的正则表达式:
1 |
|
(?:([A-Za-z]+):)?
这个因子匹配一个协议名,但仅当它之后跟随一个冒号(:)的时候才匹配(?:...)
表示一个非捕获型分组(noncapturing group),通常用非捕获分组来代替少量不优美的捕获型分组是很好的方法,因为捕获会有性能上的缺失.后缀?
表示这个分组是可选的.(...)
表示一个捕获型分组(capturing group).一个捕获型分组将复制它所匹配的文本,并将其放入到result数组中.每个捕获型分组都将被指定一个编号,第一个捕获分组的编号是1,所以该分组所匹配的文本拷贝将出现在result[1]
中;下一个因子(\/{0,3})
是捕获分组2.
常用正则
匹配数字
1 | pattern_number = /^-?\d+(?:\.\d*)?(?:e[+\-]?\d+)?$/i |
正则表达式转义
\1
指向分组1所捕获到的文本的一个引用,所以它能够再次匹配,例如我们用下面的正则表达式来搜索文本中重复的单词:
1 | var doubled_words = /[A-Za-z\u00c0-\u1fff\u2800-\ufffd\-]+\s+\1/gi |
正则表达式分组
捕获型
一个被包围在圆括号中的正则表达式选择.任何匹配这个分组的字符将被捕获.每个捕获分组都被指定了一个数字,第一个捕获(的是分组1,第二个捕获(的是分组2
非捕获型
有一个(?:
前缀,仅做简单匹配,并不会捕获所匹配文本,会有微弱的性能优势,不会干扰捕获型分组的编号.
关于语言本身的一些探讨
位运算
由于javascript中所有数字都是浮点型,所以使用位运算会降低程序性能,因为需要将数字转化为整型后执行运算然后转化回去.
巧妙使用位运算可以创造很多的奇淫技巧。例如以下的转化为整数的代码:
1 | let parseInt = num => num | 0 |
以上的parseInt
实现可以传入任意的数据类型,如果数据类型不匹配将会被转化为0,避免了原生的parseInt
中的NaN
的问题,但是局限在于只能处理32位的整数。
生成随机字母数字字符串
1 | function generateRandomAlphaNum(len) { |
toString(36)
表示10个阿拉伯数字和26个小写英文字母
随机背景色
1 | '#'+(0x1000000+(Math.random())*0xffffff).toString(16).substr(1,6) |
实现 sleep
generator
1 | function sleep(ms) { |
参见知乎
underscore.js中的_.after方法
该方法可以根据传入的times参数的不同生成需要调用多次才执行的实际函数的函数,这是偏函数的典型应用
1 | var _ = require('underscore') |
其内部实现如下:
1 | _.after = function(times, func) { |