作者:知乎用户
链接:https://www.zhihu.com/question/48187821/answer/110002647
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

出一个谷歌工程师的作品,一行代码可以看到所有页面元素。而当中包含的知识点非常多。

108 byte version:

[].forEach.call($$("*"),function(a){a.style.outline="1px solid #"+(~~(Math.random()*(1<<24))).toString(16)})

131 byte version:

[].forEach.call(document.querySelectorAll("*"),function(a){a.style.outline="1px solid #"+(~~(Math.random()*(1<<24))).toString(16)})

来源:https://gist.github.com/addyosmani/fd3999ea7fce242756b1

&amp;amp;lt;img src="https://pic4.zhimg.com/50/5f2d94eb2546d1a9b195d55567912d4f_hd.png" data-rawwidth="2798" data-rawheight="1546" class="origin_image zh-lightbox-thumb" width="2798" data-original="https://pic4.zhimg.com/5f2d94eb2546d1a9b195d55567912d4f_r.png"&amp;amp;gt;&amp;amp;lt;img src="https://pic1.zhimg.com/50/812fb2e051e3581026c8226582c325a8_hd.png" data-rawwidth="2828" data-rawheight="1598" class="origin_image zh-lightbox-thumb" width="2828" data-original="https://pic1.zhimg.com/812fb2e051e3581026c8226582c325a8_r.png"&amp;amp;gt;&amp;amp;lt;img src="https://pic3.zhimg.com/50/2846cdee38f4a4d35142bf8b5c5497fa_hd.png" data-rawwidth="2792" data-rawheight="1612" class="origin_image zh-lightbox-thumb" width="2792" data-original="https://pic3.zhimg.com/2846cdee38f4a4d35142bf8b5c5497fa_r.png"&amp;amp;gt;

中文分析

现在我们有了一个所有元素的节点列表(NodeList),现在我们想遍历它们,并给他们加上有颜色的边框。我们先看看能从这行代码里发现什么:

[].forEach.call( $$('*'), function( element ) { /* And the modification code here */ });

NodeList看起来像一个Array(数组),你可以使用中括号来访问他们的节点,而且你还可以通过length属性知道它有多少元素。但是它并没有实现Array的所有接口,因此使用 $$('*').forEach 会返回错误,在JavaScript的世界里,有一堆看起来像Array但其实不是的对象。如function中的arguments对象。因此在他们身上通过call和apply来应用数组的方法是非常有用的。我之前写过一篇文章来解析它们的用法,下面是一个例子

function say(name) {
console.log( this + ' ' + name );
} say.call( 'hola', 'Mike' );
// 打印输出 'hola Mike'

之前的一行代码使用 [].forEach.call 代替 Array.prototype.forEach.call 减少了代码的编写量 ( 另外一个很有意思的地方 );如果$$('*')返回是个数组的话,它与$$('*').forEach是等价的。

如果你看看评论,还有人使用for(i=0;A=$$('*');)让代码变得更短,但是它在全局对象中注入了变量。

你可以带上var声明,如

for(var i=0,B=document.querySelectorAll('*');A=B[i++];){ /* your code here */ }

其中i和B将只声明在console的上下文中。

改变元素的颜色
让元素有一个漂亮的边框,这行代码使用了CSS的outline属性。有一点你可能不知道,在CSS渲染的盒子模型(Box Model)中,outline并不会改变元素及其布局的位置。因此这比使用border属性要好得多,所以这一部分其实并不难理解

a.style.outline="1px solid #" + color

怎样定义颜色值其实是比较有意思的

~~(Math.random()*(1<<24))).toString(16)

我不是特别懂位运算,因此我最喜欢这一段。

我们想构造的其实是一个16进制的颜色值,像白色FFFFFF,蓝色0000FF等等。

首先我们学到了可以使用数字类型的toString方法进行十进制到16进制的转换。

其实你可以用它进行任意进制的转换

(30).toString();   // "30"
(30).toString(10); // "30"
(30).toString(16); // "1e" 16进制
(30).toString(2); // "11110" 二进制
(30).toString(36); // "u" 36 是最大允许的进制

因此16进制中的ffffff其实是 parseInt("ffffff", 16) == 16777215,16777215是2^24 - 1的值

因此左位移操作乖以一个随机数 Math.random()*(1<<24) 可以得到一个0 到 16777216之间的值

但是还不够,Math.random返回的是一个浮点数字,我们只需要整数部,这里使用了“~”操作符(按位取反操作)。

这行代码并不关心正负值。因此通过两次取返就可以得到纯整数部,我们还可以将~~视为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

如果你仔细看评论你会知道使用 按位或 "|"操作符也可以得到相同的结果。

~~a == 0|a == parseInt(a, 10)
~~b == 0|b == parseInt(b, 10)
~~c == 0|c == parseInt(c, 10)

我们最终得到了一个 0 到 16777216之间的随机数,然后使用toString(16)转换成16进制,它就是这样工作的。

原文地址:Learning much javascript from one line of code

翻译地址:从一行CSS调试代码中学到的JavaScript知识

js实现强大功能的更多相关文章

  1. 基于Node.js的强大爬虫 能直接发布抓取的文章哦

    基于Node.js的强大爬虫 能直接发布抓取的文章哦 基于Node.js的强大爬虫能直接发布抓取的文章哦!本爬虫源码基于WTFPL协议,感兴趣的小伙伴们可以参考一下 一.环境配置 1)搞一台服务器,什 ...

  2. C#设计模式总结 C#设计模式(22)——访问者模式(Vistor Pattern) C#设计模式总结 .NET Core launch.json 简介 利用Bootstrap Paginator插件和knockout.js完成分页功能 图片在线裁剪和图片上传总结 循序渐进学.Net Core Web Api开发系列【2】:利用Swagger调试WebApi

    C#设计模式总结 一. 设计原则 使用设计模式的根本原因是适应变化,提高代码复用率,使软件更具有可维护性和可扩展性.并且,在进行设计的时候,也需要遵循以下几个原则:单一职责原则.开放封闭原则.里氏代替 ...

  3. js插件---强大的图片裁剪Cropper

    js插件---强大的图片裁剪Cropper 一.总结 一句话总结:官网或者github里面的文档或者demo才是真的详细 使用的话找到图片裁剪后的base64数据,然后这个数据可下载可传递到服务器 1 ...

  4. JS实现注销功能

    JS实现注销功能,代码如下: <script> window.history.forward(1); </script> 这个代码的用法就是: 比如,我们此时有两个页面:Log ...

  5. JS的强大

    JS很强大,对于网页设计者来说,会用JS真的很重要. 学好我的linux,和数据结构.

  6. JS全选功能代码优化

    原文:JS全选功能代码优化 JS全选功能代码优化 最近在看javascript MVC那本书,也感觉到自己写的代码也并不优雅,所以一直在想 用另一种模式来编写JS代码,所以针对之前的简单的JS全选功能 ...

  7. FM收音机 RDS的强大功能

    FM收音机 RDS的强大功能 分类: MTK2011-04-26 16:06 14889人阅读 评论(6) 收藏 举报 交通公告体育音乐娱乐教育 前言 随着发展,会有越来越多的电台具有RDS广播功能, ...

  8. CI 结合 vue.js 的搜索功能模块

    CI 结合 vue.js 的搜索功能模块 最近在有优化公司后台的某个模块的搜索功能优化 原先的是这个样子的,很是单调: 老大给我找个图希望我能弄成这样子: 经过不断修改,最后成了这样子 是不是比以前好 ...

  9. Python和SQL Server 2017的强大功能

    Python和SQL Server 2017的强大功能 摘要: 源:https://www.red-gate.com/simple-talk/sql/sql-development/power-pyt ...

随机推荐

  1. HTML超文本

    1.HTML链接 2.HTML表格 3.HTML图像 4.HTML列表 5.HTML块 6.HTML布局 7.HTML表单 1.HTML链接 (1)给文字及图片添加超链接 < html> ...

  2. Angular2 Service实践

    引言: 如果说组件系统(Component)是ng2应用的躯体,那把服务(Service)认为是流通于组件之间并为其带来生机的血液再合适不过了.组件间通信的其中一种优等选择就是使用服务,在ng1里就有 ...

  3. 走进Node.js 之 HTTP实现分析

    作者:正龙(沪江Web前端开发工程师) 本文为原创文章,转载请注明作者及出处 上文"走进Node.js启动过程"中我们算是成功入门了.既然Node.js的强项是处理网络请求,那我们 ...

  4. Javascript中的noscript

    引言: 在浏览器日常火爆的时代,个大浏览器几乎都想占主导地位,争个你死我活,所以现在的各大浏览器都支持javascript脚本语言,但是在童鞋们,我们假设一下,万一哪个用户出于安全,把浏览器的java ...

  5. U方法

    U方法用于完成对URL地址的组装,特点在于可以自动根据当前的URL模式和设置生成对应的URL地址,格式为:U('地址','参数','伪静态','是否跳转','显示域名');在模板中使用U方法而不是固定 ...

  6. mybatis运行时错误Illegal argument exception argument type mismatch

    使用注解时遇到该错误 使用XML应该也会有相应的错误 解决办法:查看是不是Dao接口的参数列表没有加@Param注解  参数过多时需要该注解指明参数

  7. LNMP环境源码搭建

    以前LNMP环境是由运维搭建,自己搭建的时候查找了很多资料,这是我见过的最棒的资料,将过程记录下来分享给大家 为啥使用LNMP而不是LAMP下面来谈谈Nginx的技能 Nginx是一个小巧而高效的Li ...

  8. 最长上升子序列 LIS(Longest Increasing Subsequence)

    引出: 问题描述:给出一个序列a1,a2,a3,a4,a5,a6,a7….an,求它的一个子序列(设为s1,s2,…sn),使得这个子序列满足这样的性质,s1<s2<s3<…< ...

  9. 关于el-dialog,我更推荐的用法

    最近的项目里用上了vue和element-ui.vue这种轻量级渐进式框架的舒适自不必说,但一直困扰着我的,是如何方便又优雅的弹出模态dialog... 对于我这种在jquery出现之前就用docum ...

  10. Fiddler屏蔽某些url的抓取方法

    在用Fiddler调试网页的时候,可能某些频繁的ajax轮询请求会干扰我们,可以通过以下方法屏蔽某些url的抓取. 在需要屏蔽的url行上右键---->“Filter Now”-----> ...