摘要:从一行代码里面学点JavaScript,现现在,JavaScript无处不在,所以关于JavaScript的新知识也是层出不穷。JavaScript的特色在于,要学习它的语法入门简简单,可是要精通使用它的方式倒是一件不容易的事。javascript
现现在,JavaScript无处不在,所以关于JavaScript的新知识也是层出不穷。JavaScript的特色在于,要学习它的语法入门简简单,可是要精通使用它的方式倒是一件不容易的事。java
来看看下面的这段代码,它来自于谷歌“名猿”Addy Osmani在几天前贴出的一段代码,它的做用是用来调试你的CSS层。所有代码只有三行,可是你绝对能够把它放在一行里面完成:程序员
[].forEach.call($$("*"),function(a){ a.style.outline="1px solid #"+(~~(Math.random()*(1<<24))).toString(16) })
如今,在你的Chrome浏览器的控制台中输入这段代码,你会发现不一样HTML层都被使用不一样的颜色添加了一个高亮的边框。是否是很是酷?可是,简单来讲,这段代码只是首先获取了全部的页面元素,而后使用一个不一样的颜色为它们添加了一个1ps的边框。想法很简单,可是真要实现起来却不是那么容易的一件事。在下面的内容中,咱们将一块儿一步一步学习如何理解上面的这段代码。数组
咱们须要作的第一件事情是获取页面中全部的元素,在上面的代码中,Addy使用了一个Chrome浏览器中特有的函数 $$
。你能够在你的Chrome浏览器控制台中输入 $$('a')
,而后你就能获得一个当前页面中全部锚元素的列表。浏览器
$$
函数是许多现代浏览器命令行API中的一个部分,它等价于 document.querySelectorAll
,你能够将一个CSS选择器做为这个函数的参数,而后你就可以得到当前页面中全部匹配这个CSS选择器的元素列表。若是你在浏览器控制台之外的地方,你可使用 document.querySelectorAll('*')
来代替 $$('*')
。更多关于 $$
函数的详细内容能够查看Chrome开发者工具的文档。app
固然,除了使用$$
函数以外,咱们还有一种更简单的方法,document.all,虽然这并非一种很规范的使用方法,可是它几乎在每个浏览器中都能运行成功。dom
通过第一步,咱们已经得到了页面内全部的元素,如今咱们想作的事情是遍历每个元素,而后为它们添加一个彩色边边框。可是上面的代码到底是怎么一回事呢?函数
[].forEach.call( $$('*'), function( element ) { /* 在这里修改颜色 */ });
首先,咱们经过选择器得到的列表是一个NodeLists对象,它和JavaScript中的数组有点像,你可使用方括号来获取其中的节点,你也能够检查它其中包含多少个元素,可是它并无实现数组包含的全部方法,所以咱们并不能使用$$('*').forEach()
来进行迭代。在JavaScript中,有好几个相似于数组可是并非数组的对象,除了前面的NodeLists,还有函数的参数集合arguments,在这里咱们可使用call或apply函数将函数的方法运用到这些对象上。例以下面的例子:工具
function say(name) { console.log( this + ' ' + name ); } say.call( 'hola', 'Mike' ); // 打印 'hola Mike' // 你也能够将这种方法有用在arguments对象上 function example( arg1, arg2, arg3 ) { return Array.prototype.slice.call(arguments, 1); // Returns [arg2, arg3] }
在Addy的代码中,使用了[].forEach.call而不是Array.prototype.forEach.call,两者等价,可是前者能够节省几个字节。布局
为了让元素都有一个漂亮的边框,咱们在上面的代码中使用了CSS属性outline。outline属性位于CSS盒模型以外,所以它并不影响元素的属性或者元素在布局中的位置,这对于咱们来讲很是有用。这个属性和修改border属性很是相似,所以下面的代码应该不会很难理解:
a.style.outline="1px solid #" + color
真正有趣的地方在于定义颜色部分:
~~(Math.random()*(1<<24))).toString(16)
天呐,上面的代码是什么意思?在JavaScript中,比特操做符并非常常被使用,所以这里可能会让不少程序员感到很疑惑。
咱们想达到的目的是活的一个十六进制格式的颜色例如白色对应的是FFFFFF,蓝色对应的是0000FF,或者随便一个颜色37f9ac。虽然咱们人类喜欢十进制,可是咱们的代码经常会须要十六进制的东西。
咱们首先要学会如何使用toString函数将一个十进制的数组转换为一个十六进制整数。这个函数能够接受一个参数,若是参数缺省,默认为十进制,可是你彻底可使用别的数组:
(30).toString(); // "30" (30).toString(10); // "30" (30).toString(16); // "1e" 十六进制 (30).toString(2); // "11110" 二进制 (30).toString(36); // "u" 36是容许的最大参数值
除此以外,你可使用parseInt函数将十六进制数字转换为十进制。
parseInt("30"); // "30" parseInt("30", 10); // "30" parseInt("1e", 16); // "30" parseInt("11110", 2); // "30" parseInt("u", 36); // "30"
所以,咱们如今只须要一个位于0和ffffff之间的十六进制数,因为:
parseInt("ffffff", 16) == 16777215
而这里的16777215其实是2^24-1。
若是你对二进制数学熟悉的话,你可能会知道1<<24 == 16777216。
再进一步,你每在1后面添加一个0,你就至关于多作了一次2的乘方:
1 // 1 == 2^0 100 // 4 == 2^2 10000 // 16 == 2^4 1000000000000000000000000 // 16777216 == 2^24
所以,在这里咱们能够知道Math.random()*(1<<24)表示一个位于0和16777216之间的数。
可是这里并无结束,由于Math.random返回的是一个浮点数,可是咱们只想要整数部分。咱们的代码中使用波浪号操做符来完成这件事。波浪操做符在JavaScript中被用来对一个变量进行取反。
可是咱们在这里并不关心取反,咱们指向获取整数部分。所以咱们还能够知道两次取反能够去掉一个浮点数的小数部分,所以~~的做用至关于parseInt:
var a = 12.34, // ~~a = 12 b = -1231.8754, // ~~b = -1231 c = 3213.000001 // ~~c = 3213 ; ~~a == parseInt(a, 10); // true ~~b == parseInt(b, 10); // true ~~c == parseInt(c, 10); // true
固然,咱们还有一种更加简洁的方法,使用OR操做符:
~~a == 0|a == parseInt(a, 10) ~~b == 0|b == parseInt(b, 10) ~~c == 0|c == parseInt(c, 10)
最终,咱们得到了一个位于0和16777216之间的随机整数,也就是咱们想要的随机颜色。此时咱们只须要使用toString(16)将它转化为十六进制数便可。
如今,你已经彻底理解了前面的这一行代码中的各个部分。做为一个程序员,咱们应该在完成工做以后多问本身几遍为何,还有没有更好更简洁的方法。固然,最应该作的事情固然是多阅读程序代码,也许你就能从某一行代码中学到不少新东西。