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


Posted in Javascript onOctober 11, 2016

记得还在懵懂学习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 里了,所以分开赋值能让加载的外部脚本读取到这里的附加参数。

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

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

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

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

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 id="one" 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

IE 11 单位:ms
第1次 第2次 第3次 第4次 第5次 第6次 第7次 第8次 第9次 第10次 平均值 10W次差值 单次差值
正常情况 2352 2332 2321 2347 2342 2339 2365 2373 2353 2343 2346.7 861.7 0.86μs

由于其它软件运行的影响及两种代码运行的先后顺序,结果可能不是十分严谨,但个人认为还是不会影响我们得出最终的结论:with语句在不是嵌套十分复杂的情况下,相比于一般代码对执行效率的影响其实微乎其微。

我想ECMAScript 5 的strict mode下禁用with语句的主要原因应该是with语句让个对象与方法与属性的关系变得更模糊, 不利于JavaScript向面向对象编程靠拢吧。

三水点靠木小编补充:虽然有B格但不论是易于阅读还是考虑性能的目的,很多网站还是使用普通的方式加载。

Javascript 相关文章推荐
表单类各种类型(文本框)失去焦点效果jquery代码
Apr 26 Javascript
JavaScript中数据结构与算法(一):栈
Jun 19 Javascript
js jquery获取当前元素的兄弟级 上一个 下一个元素
Sep 01 Javascript
jQuery实现的经典滑动门效果
Sep 22 Javascript
跟我学习javascript创建对象(类)的8种方法
Nov 20 Javascript
详解javascript实现瀑布流列式布局
Jan 29 Javascript
JavaScript正则表达式匹配 div  style标签
Mar 15 Javascript
JavaScript简单实现弹出拖拽窗口(二)
Jun 17 Javascript
JS控制文本域只读或可写属性的方法
Jun 24 Javascript
jQuery实现动态控制页面元素的方法分析
Dec 20 jQuery
jQuery实现百度图片移入移出内容提示框上下左右移动的效果
Jun 05 jQuery
JS获取动态添加元素的方法详解
Jul 31 Javascript
Node.js的文件权限及读写flag详解
Oct 11 #Javascript
最原始的jQuery注册验证方式
Oct 11 #Javascript
js正则表达式注册页面表单验证
Oct 11 #Javascript
jQuery ajax MD5实现用户注册即时验证功能
Oct 11 #Javascript
完美解决js传递参数中加号和&amp;号自动改变的方法
Oct 11 #Javascript
浅谈在js传递参数中含加号(+)的处理方式
Oct 11 #Javascript
JS验证图片格式和大小并预览的简单实例
Oct 11 #Javascript
You might like
PHP中防止SQL注入实现代码
2011/02/19 PHP
如何让thinkphp在模型中自动完成session赋值小教程
2014/09/05 PHP
CI框架中cookie的操作方法分析
2014/12/12 PHP
微信公众号开发之通过接口删除菜单
2017/02/20 PHP
PHP获取文件扩展名的方法实例总结
2017/06/10 PHP
深入理解PHP+Mysql分布式事务与解决方案
2020/12/03 PHP
ANGULARJS中使用JQUERY分页控件
2015/09/16 Javascript
javascript图片预加载完整实例
2015/12/10 Javascript
微信小程序 http请求详细介绍
2016/10/09 Javascript
JS实现电话号码的字母组合算法示例
2019/02/26 Javascript
详解微信图片防盗链“此图片来自微信公众平台 未经允许不得引用”的解决方案
2019/04/04 Javascript
详解滑动穿透(锁body)终极探索
2019/04/16 Javascript
用node.js写一个jenkins发版脚本
2019/05/21 Javascript
微信内置开发 iOS修改键盘换行为搜索的解决方案
2019/11/06 Javascript
搭建vscode+vue环境的详细教程
2020/08/31 Javascript
Nodejs在局域网配置https访问的实现方法
2020/10/17 NodeJs
[05:05]DOTA2亚洲邀请赛 战队出场仪式
2015/02/07 DOTA
[50:54]完美世界DOTA2联赛 GXR vs IO 第三场 11.07
2020/11/10 DOTA
Python访问纯真IP数据库脚本分享
2015/06/29 Python
python正则表达式面试题解答
2020/04/28 Python
Python使用selenium实现网页用户名 密码 验证码自动登录功能
2018/05/16 Python
Flask框架Jinjia模板常用语法总结
2018/07/19 Python
Python中staticmethod和classmethod的作用与区别
2018/10/11 Python
pyqt5与matplotlib的完美结合实例
2019/06/21 Python
详解python uiautomator2 watcher的使用方法
2019/09/09 Python
Python中sorted()排序与字母大小写的问题
2020/01/14 Python
详解Python修复遥感影像条带的两种方式
2020/02/23 Python
Scrapy模拟登录赶集网的实现代码
2020/07/07 Python
谷歌浏览器小字体处理方案即12px以下字体
2013/12/17 HTML / CSS
HTML5手指下滑弹出负一屏阻止移动端浏览器内置下拉刷新功能的实现代码
2020/04/10 HTML / CSS
英国最大的在线快递公司之一:ParcelHero
2019/11/04 全球购物
西班牙品牌鞋子、服装和配饰在线商店:Esdemarca
2021/02/17 全球购物
日本整理专家Marie Kondo的官方在线商店:KonMari
2020/06/29 全球购物
2014年元旦感言
2014/03/06 职场文书
工地安全生产标语
2014/06/06 职场文书
彻底解决MySQL使用中文乱码的方法
2022/01/22 MySQL