本文来自 @张小俊128;链接:http://www.html-js.com/article/A-day-to-learn-from-a-line-of-code-inside-the-JavaScript-study-JavaScript

现如今,JavaScript无处不在,因此关于JavaScript的新知识也是层出不穷。JavaScript的特点在于,要学习它的语法入门简简单,但是要精通使用它的方式却是一件不容易的事。

来看看下面的这段代码,它来自于谷歌“名猿”Addy Osmani在几天前贴出的一段代码,它的作用是用来调试你的CSS层。全部代码只有三行,但是你绝对可以把它放在一行里面完成:

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

现在,在你的Chrome浏览器的控制台中输入这段代码,你会发现不同HTML层都被使用不同的颜色添加了一个高亮的边框。是不是非常酷?但是,简单来说,这段代码只是首先获取了所有的页面元素,然后使用一个不同的颜色为它们添加了一个1px的边框。想法很简单,但是真要实现起来却不是那么容易的一件事。在下面的内容中,我们将一起一步一步学习如何理解上面的这段代码。

选择页面中所有的元素

我们需要做的第一件事情是获取页面中所有的元素,在上面的代码中,Addy使用了一个Chrome浏览器中特有的函数$$。你可以在你的Chrome浏览器控制台中输入$$('a'),然后你就能得到一个当前页面中所有锚元素的列表。

$$函数是许多现代浏览器命令行API中的一个部分,它等价于document.querySelectorAll,你可以将一个CSS选择器作为这个函数的参数,然后你就能够获得当前页面中所有匹配这个CSS选择器的元素列表。如果你在浏览器控制台以外的地方,你可以使用document.querySelectorAll('*')来代替$$('*')。更多关于$$函数的详细内容可以查看Chrome开发者工具的文档。

当然,除了使用$$函数之外,我们还有一种更简单的方法,document.all,虽然这并不是一种很规范的使用方法,但是它几乎在每一个浏览器中都能运行成功。

迭代所有的元素

经过第一步,我们已经获得了页面内所有的元素,现在我们想做的事情是遍历每一个元素,然后为它们添加一个彩色边边框。但是上面的代码究竟是怎么一回事呢?

[].forEach.call( $$('*'), function( element ) { /* 在这里修改颜色 */ });

首先,我们通过选择器获得的列表是一个NodeLists对象,它和JavaScript中的数组有点像,你可以使用方括号来获取其中的节点,你也可以检查它其中包含多少个元素,但是它并没有实现数组包含的所有方法,因此我们并不能使用$$('*').forEach()来进行迭代。在JavaScript中,有好几个类似于数组但是并不是数组的对象,除了前面的NodeLists,还有函数的参数集合arguments,在这里我们可以使用callapply函数将函数的方法运用到这些对象上。例如下面的例子:

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属性outlineoutline属性位于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 = 12b = -1231.8754, // ~~b = -1231c = 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)将它转化为十六进制数即可。

总结

现在,你已经完全理解了前面的这一行代码中的各个部分。作为一个程序员,我们应该在完成工作之后多问自己几遍为什么,还有没有更好更简洁的方法。当然,最应该做的事情当然是多阅读程序代码,也许你就能从某一行代码中学到很多新东西。

转载于:https://www.cnblogs.com/chenrf/p/10095527.html

前端读者 | 从一行代码里面学点JavaScript相关推荐

  1. 一行js_不用引入JQuery,前端开发们一行代码就能使用的提示信息开源组件

    在一个 Web 项目中,其实前端开发者们只需要一个加载中,或者一个好看的提示信息.这么一个简单的目的,却要引入各种各样的东西,十分复杂.今天为大家推荐的 msg.js 就让前端开发者们只需一行代码,就 ...

  2. 我是如何用一行代码表白学妹~❤520情人节送女朋友的3D樱花雨相册礼物❤~(程序员表白专属)

    ❉ 520情人节送女朋友的3D相册礼物~html+css+js实现抖音炫酷樱花3D相册(含音乐+自定义文字) 一年一度的520情人节/七夕情人节/女朋友生日/程序员表白,是不是要给女朋友或者正在追求的 ...

  3. 我是如何用一行代码表白学妹~❤520情人节送女朋友的3D樱花雨相册礼物❤~(程序员表白专属)...

    ❉ 520情人节送女朋友的3D相册礼物~html+css+js实现抖音炫酷樱花3D相册(含音乐+自定义文字) 一年一度的520情人节/七夕情人节/女朋友生日/程序员表白,是不是要给女朋友或者正在追求的 ...

  4. 一行代码教你七夕情人节如何告白❤—动漫3D相册(音乐+文字)HTML+CSS+JavaScript

    ❤ 一行代码教你七夕情人节如何告白-动漫3D相册(音乐+文字)HTML+CSS+JavaScript 七夕是中国的情人节,七夕520情人节也是一个非常适合表白的日子,可以把自己平常害怕说出来的话,在这 ...

  5. 从 vue3 和 vite 源码中,我学到了一行代码统一规范团队包管理器的神器

    1. 前言 大家好,我是若川.最近组织了源码共读活动,感兴趣的可以加我微信 ruochuan12 参与,每周大家一起学习200行左右的源码,共同进步.已进行四个月了,很多小伙伴表示收获颇丰. 想学源码 ...

  6. 如何把python可视化到前端_Python一行代码搞定炫酷可视化,就用这个工具!

    学过Python数据分析的朋友都知道,在可视化的工具中,有很多优秀的三方库,比如matplotlib,seaborn,plotly,Boken,pyecharts等等.这些可视化库都有自己的特点,在实 ...

  7. 首次开源!一行代码轻松搞定中英文语音识别、合成、翻译核心功能!

    导读 要说生活里最常见的AI应用场景,语音合成与识别当属大家最为耳熟能详的场景之一了. 寻常到平时地图导航的播报.微信语音转文字.手机语音输入,以及小度智能音箱,都离不开语音技术的加持. 语音技术到底 ...

  8. 重磅!百度飞桨开源语音基础模型库|中英文语音识别、语音翻译、语音合成、声音分类通通一行代码轻松搞定...

    导读 要说生活里最常见的AI应用场景,语音合成与识别当属大家最为耳熟能详的场景之一了. 寻常到平时地图导航的播报.微信语音转文字.手机语音输入,以及小度智能音箱,都离不开语音技术的加持. 语音技术到底 ...

  9. 重磅!一行代码轻松搞定中英文语音识别与语音合成|代码开源!

    导读 要说生活里最常见的 AI 应用场景,语音合成与识别当属大家最为耳熟能详的场景之一了. 寻常到平时地图导航的播报.微信语音转文字.手机语音输入,以及小度智能音箱,都离不开语音技术的加持. 语音技术 ...

  10. 一行代码解决各种IE兼容问题

    一行代码解决各种IE兼容问题,IE6,IE7,IE8,IE9,IE10 前端面试秘籍,欢迎star! 在网站开发中不免因为各种兼容问题苦恼,针对兼容问题,其实IE给出了解决方案Google也给出了解决 ...

最新文章

  1. 字节AI Lab总监李磊离职加入UCSB,马维英后又一大牛回归学界
  2. 在近期,美众议院为何密集提出了15项新兴技术法案?
  3. mysql的总结7--存储过程
  4. 神经网络与机器学习 笔记—核方法和径向基函数网络(下)
  5. Java Web - 服务器中的过滤器和监听器
  6. 【搜索引擎基础知识2】网络爬虫
  7. [Leetcode][第44题][JAVA][通配符匹配][贪心][动态规划]
  8. 【NLP专栏】图解 BERT 预训练模型!
  9. 浅入浅出 Java 排序算法
  10. Python使用心得之魔法参数**kw
  11. php算法调度先来先服务器,高响应比优先调度算法
  12. 来自资深程序员的 3 条锦囊:永远不要辞职,除非……
  13. 日版IPhone5完美上3G
  14. 零基础一次通过软考网络工程师经验分享
  15. macOS开发中用TagLib获取、修改音频文件信息
  16. 高光时刻 | 方正璞华联合开发的「人力资源法律服务共享平台」在创新创业大赛中获奖
  17. uni-app动态设置原生标题左侧按钮
  18. 月亮私房菜——秘制辣椒油!让你辣得够味!辣得过瘾!
  19. (十)MySQL中的逻辑条件 优先规则 排序(未完版)
  20. 云主机如何保证信息安全?

热门文章

  1. nyoj--32--组合数
  2. 不会点SQLite,都不好意思说自己是开发的 1
  3. 无废话WPF系列16:资源
  4. 【设计模式】解释器模式
  5. Android开发中的SQLite事务处理,即beginTransaction()方法
  6. Red5服务器端报错:无法解析类型ResourcePatternResolver
  7. 每天一点Linux --- 在Linux终端下调用当前目录下的可执行文件时需要加上./的原因...
  8. corosynclib+drbd+mysql组合应用
  9. 子DIV块中设置margin-top时影响父DIV块位置的解决办法
  10. protobuf反射详解及应用(pb/json相互转换)