[转]从一行代码里面学点JavaScript
现如今,JavaScript无处不在,因此关于JavaScript的新知识也是层出不穷。JavaScript的特点在于,要学习它的语法入门简简单,但是要精通使用它的方式却是一件不容易的事。
来看看下面的这段代码,它来自于谷歌“名猿”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开发者工具的文档。
当然,除了使用$$
函数之外,我们还有一种更简单的方法,document.all
,虽然这并不是一种很规范的使用方法,但是它几乎在每一个浏览器中都能运行成功。
迭代所有的元素
经过第一步,我们已经获得了页面内所有的元素,现在我们想做的事情是遍历每一个元素,然后为它们添加一个彩色边边框。但是上面的代码究竟是怎么一回事呢?
[].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)
将它转化为十六进制数即可。
总结
现在,你已经完全理解了前面的这一行代码中的各个部分。作为一个程序员,我们应该在完成工作之后多问自己几遍为什么,还有没有更好更简洁的方法。当然,最应该做的事情当然是多阅读程序代码,也许你就能从某一行代码中学到很多新东西。
英文原文地址:http://arqex.com/939/learning-much-javascript-one-line-code
[转]从一行代码里面学点JavaScript的更多相关文章
- 从一行代码里面学点JavaScript
从一行代码里面学点JavaScript 现如今,JavaScript无处不在,因此关于JavaScript的新知识也是层出不穷.JavaScript的特点在于,要学习它的语法入门简简单,但是要精通使用 ...
- 前端读者 | 从一行代码里面学点JavaScript
本文来自 @张小俊128:链接:http://www.html-js.com/article/A-day-to-learn-from-a-line-of-code-inside-the-JavaScr ...
- NodeJS服务器:一行代码 = 一个的HTTP服务器
从这一篇开始,我们进入技术讲解的话题,逐步实现用NodeJS实现文件的传送共享服务. 前文我们讲过,NodeJS是最擅长做网络服务器的,今天我们就来用NodeJS做一个最简单的服务器. 先看一幅图: ...
- 一行能装逼的JavaScript代码
一行能装逼的JavaScript代码 2016-06-28 野狗 一行神奇的JS代码,当时我就震 惊了,这不就是传说中的ZB神奇么… … 哈哈. 写本篇文章的缘由是之前看到了一段js代码,如下: (! ...
- Asp.Net Core 轻松学-一行代码搞定文件上传 JSONHelper
Asp.Net Core 轻松学-一行代码搞定文件上传 前言 在 Web 应用程序开发过程中,总是无法避免涉及到文件上传,这次我们来聊一聊怎么去实现一个简单方便可复用文件上传功能:通过创建 ...
- 一行能装逼的JavaScript代码的延伸
前段就是坑,入坑水真深. 先看看一个黑科技, 纳尼,这是什么东西. (!(~+[])+{})[--[~+""][+[]]*[~+[]] + ~~!+[]]+({}+[])[[~!+ ...
- 33个非常实用的JavaScript一行代码
33个非常实用的JavaScript一行代码 一.日期处理 1. 检察日期是否有效 该方法用于检测给出的日期是否有效: const isDateValid = (...val) => !Numb ...
- 微软出品自动化神器Playwright,不用写一行代码(Playwright+Java)系列(一) 之 环境搭建及脚本录制
一.前言 半年前,偶然在视频号刷到某机构正在直播讲解Playwright框架的使用,就看了一会,感觉还不错,便被种草,就想着自己有时间也可以自己学一下,这一想着就半年多过去了. 读到这,你可能就去百度 ...
- 一行代码解决各种IE兼容问题,IE6,IE7,IE8,IE9,IE10
行代码解决各种IE兼容问题,IE6,IE7,IE8,IE9,IE10 2012-04-25 16:29:04| 分类: 学习 |字号 订阅 在网站开发中不免因为各种兼容问题苦恼,针对兼容问题,其实IE ...
随机推荐
- 我的第一篇博客 ——【ToDoList】小程序开发
我是一只即将大四的大三狗,这是我的第一篇博客,说来惭愧.今年1月份,学校放寒假的时候开始自学的IOS,放假的时候比较起劲,看了一堆Object-C的视频,然后照着中英文对照的IOS基础开发教程,做了两 ...
- hdu 1392凸包周长
//用的自己的计算几何模板,不过比较慢嘿嘿 //要注意只有一个点和两个点 //Computational Geometry //by kevin_samuel(fenice) Soochow Univ ...
- 如何让OpenSSL得到JKS格式的keystore中的public and private key
国内私募机构九鼎控股打造APP,来就送 20元现金领取地址:http://jdb.jiudingcapital.com/phone.html内部邀请码:C8E245J (不写邀请码,没有现金送)国内私 ...
- 给postfix设置黑名单
国内私募机构九鼎控股打造APP,来就送 20元现金领取地址:http://jdb.jiudingcapital.com/phone.html内部邀请码:C8E245J (不写邀请码,没有现金送)国内私 ...
- HubbleDotNet 学习之路
1.创建后台任务实现自动同步更新表数据.打开工具后点击“management”选项卡,选择“task scheduler management”,在弹出的窗口中点击右侧的"add" ...
- 7 种流行 PHP IDE 的比较
编写关于 PHP 的系列文章让我更加深刻地了解了 PHP 开发人员的世界.我和许多 PHP 程序员交谈过,最令我惊奇的是只有很少的人使用 IDE.大多数程序员使用文本编辑器,比如 Microsoft® ...
- android利用zbar二维码扫描-(解决中文乱码及扫描区域定义)
写在最前(这是对上一篇博文的问题做的更新[android利用zbar二维码扫描]) project下载 zbarLib编译project project下载0积分 bug 在2.3的系统中Hol ...
- 《RESTful Web Services》第二章 识别资源
引言:开放RESTful Web服务的首要步骤之一是设计资源模型. 2.1 如何从领域名词中识别资源 2.2 如何选择资源粒度 一些因素会影响数据库表和对象模型的设计,例如领域建模.需要高 ...
- linux 学习笔记 Linux内核的四大功能简介
一 内存管理 默认情况下,运行在Linux系统上的每个进程都有各自的内存页面:进程不能访问其他进程正在使用的内存页面. 内核维护着自己的内存区域 用户进程不能访问内核进程的内存 可以创建一些共享内存页 ...
- iOS-label出现未知边框线的bug
在前段时间碰到了一个问题 label上出现了一个位置的右边框 仔细查看代码发现没有指定边框 而且奇怪的是只显示右边框 其他边框没有显示 需求效果图: 实际效果图: 结构图: 通过查看结构图 可 ...