javascript之with的使用(阿里云、淘宝使用代码分析

记得还在懵懂学习JavaScript基础之时,坊间便有传言“with语句是低效率语句,若非必要,请不要使用该语句”,同时, ECMAScript 5 的strict mode下是禁止使用with语句的,所以一直以来我对with语句一直没啥好感。

今天在知乎有个话题大概说的是“你觉得什么东西相当有B格”之类的,然后就有人贴了这段代码:

with(document)with(body)with(insertBefore(createElement("script"), firstChild))setAttribute("exparams","category=&userid=68497352&aplus&yunid=", id = "tb-beacon-aplus", src = (location > "https" ? "//s": "//a") + ".tbcdn.cn/s/aplus_v2.js")

代码拆解:

with(document) with(body) with(insertBefore(createElement("script"), firstChild)) setAttribute("exparams","category=&userid=68497352&aplus&yunid=", id = "tb-beacon-aplus", src = (location > "https" ? "//s": "//a") + ".tbcdn.cn/s/aplus_v2.js" )

再拆开

var script = document.createElement("script"); document.body.insertBefore(script, document.body.firstChild); script.setAttribute("exparams","category=&userid=68497352&aplus&yunid=", script.id = "tb-beacon-aplus", script.src = (location > "https" ? "//s": "//a") + ".tbcdn.cn/s/aplus_v2.js" );

因为在 JavaScript 里,可以给函数多传一些无用参数的。
因此,最后这句话完全可以理解为:
script.id = "tb-beacon-aplus";
script.src = (location > "https" ? "//s": "//a") + ".tbcdn.cn/s/aplus_v2.js";
script.setAttribute("exparams","category=&userid=68497352&aplus&yunid=");

如果赋值的不是标准属性,就不会写出到标签的 attribute 里了,所以分开赋值能让加载的外部脚本读取到这里的附加参数。

据说是淘宝首页的,好奇心使然,果断跑去淘宝看了下,有图有真相哪:

淘宝这种大项目一般是十分讲究效率的,居然会使用传说中的低效率代码?

我们试着用正常代码来达到上面的功能:

var s = document.createElement("script"); s.setAttribute("exparams","category=&userid=68497352&aplus&yunid="); s.setAttribute("src",(location>"https"?"//s":"//a")+".tbcdn.cn/s/aplus_v2.js"); s.id="tb-beacon-aplus"; document.body.insertBefore(s,document.body.firstChild)

这是我能写出的最简单的代码了,当然,您可以尝试像淘宝那代码一样setAttribute,不过结果会让你很受伤!!!经过我的测试,他那样带3个以上的参数设置节点属性仅在with语句下有效,而且第三个及以后参数所设置的属性只能是HTML标准属性。原因我也不知道,有大牛愿意指教么?

代码压缩后,淘宝代码224字节,我写的代码264字节。

我得出的结论是:大的网站惜字节如金,特别是像淘宝这种每天流量巨大的网站,为了节省流量(别看只有几个字节,乘以个大的访问量后结果还是挺惊人的)而稍微牺牲下用户代码运行的效率是完全值得的。况且,在浏览器代码执行效率日新月异的今天,with语句效率真有那么低么?

秉承一颗探索的心(此刻内心略为激动。。),做了如下代码测试,

html代码:

<!doctype html> <html lang="en"> <head>     <meta charset="UTF-8">     <title>test</title> </head> <body>     <div data="test data"></div> </body> </html>

with语句获取div#data值

var now = +new Date; for(var i=0;i<1000000;i++){    with(document)with(getElementById("one"))getAttribute("data") } console.log(new Date-now)

一般代码获取div#one的data值

var now = +new Date; for(var i=0;i<1000000;i++){    document.getElementById("one").getAttribute("data") } console.log(new Date-now)

获取属性值的代码均循环运行100W次,输出运行时间,测试浏览器为Chrome 35与IE 11:

申明:谁特么说我是IE黑,我和谁急!!!

Chrome 35   数值单位:ms  
  第1次   第2次   第3次   第4次   第5次   第6次   第7次   第8次   第9次   第10次   平均值   10W次差值   单次差值  
一般代码   1362   1358   1379   1377   1372   1411   1371   1341   1356   1339   1366.6   888.7   0.89μs  

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wzdspy.html