问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

如何理解“匿名自执行函数是为了保护变量名泄露到外部可见”?_百度...

发布网友 发布时间:2022-04-27 03:26

我来回答

2个回答

热心网友 时间:2022-04-20 04:11

是的。这里的变量也包括函数。函数也是一种变量。匿名写法可以避免变量全局污染。

比如。在别人写过的一段js代码中你想在里面加一些自己的代码。最好的做法就是用匿名函数包裹。举个例子来看为什么。

比如,已经存在一段别人写的代码了,假设这段代码很长你不想看。

//别人的代码
....
....很多
//这里他定义了一个叫foo的函数
function foo{
 ... 一些函数逻辑
}


好,现在你自己想在同一个页面里面加一些自己的代码。假如你不知道别人已经定义了foo函数,你又额外在自己的函数里面定义一次

function foo{
 ..
}

把这段代码加在了页面的最后。这样你的函数定义就覆盖了 原来别人i写的函数定义。

恰巧,在某个事件里面,就使用foo函数。这个时候,原来的逻辑就不能正确执行了。


假如你的定义写在匿名函数里面, 那么这个定义就对外部不可见的,不会覆盖原来的。这样就避免了变量污染。 实际的应用,你就去参考 流行js库的源代码。通常都是如下写法

;(function(){
 var ....
 ....
})()

这样就会避免变量污染了。

注意,在开始的第一个字符 使用 分号,这是因为避免出现代码压缩时产生意外的错误。因为js可以省写分号。假设有段代码是

....
return result

然后又在js合并压缩时 合并成一个文件

...
return reslut;(function(){...})()


如果没有分号就会成这样

....
return reslut(function(){...})()

在代码进行压缩后result 变成了一个函数了,这明显是错误的。


因此在匿名函数的前面加个 分号 也是个良好的习惯

热心网友 时间:2022-04-20 05:29

一、同步加载与异步加载的形式
1. 同步加载
我们平时最常使用的就是这种同步加载形式:
<script src="http://yourdomain.com/script.js"></script>

同步模式,又称阻塞模式,会阻止浏览器的后续处理,停止了后续的解析,因此停止了后续的文件加载(如图像)、渲染、代码执行。
js 之所以要同步执行,是因为 js 中可能有输出 document 内容、修改dom、重定向等行为,所以默认同步执行才是安全的。
以前的一般建议是把<script>放在页面末尾</body>之前,这样尽可能减少这种阻塞行为,而先让页面展示出来。
简单说:加载的网络 timeline 是瀑布模型,而异步加载的 timeline 是并发模型。
2. 常见异步加载(Script DOM Element)
(function() { var s = document.createElement('script'); s.type = 'text/javascript'; s.async = true; s.src = 'http://yourdomain.com/script.js'; var x = document.getElementsByTagName('script')[0]; x.parentNode.insertBefore(s, x); })();

异步加载又叫非阻塞,浏览器在下载执行 js 同时,还会继续进行后续页面的处理。
这种方法是在页面中<script>标签内,用 js 创建一个 script 元素并插入到 document 中。这样就做到了非阻塞的下载 js 代码。
async属性是HTML5中新增的异步支持,见后文解释,加上好(不加也不影响)。
此方法被称为 Script DOM Element 法,不要求 js 同源。
将js代码包裹在匿名函数中并立即执行的方式是为了保护变量名泄露到外部可见,这是很常见的方式,尤其是在 js 库中被普遍使用。
例如 Google Analytics 和 Google+ Badge 都使用了这种异步加载代码:
(function() { var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true; ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s); })();

(function()
{var po = document.createElement("script"); po.type = "text/javascript"; po.async = true;po.src = "https://apis.google.com/js/plusone.js"; var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(po, s); })();

但是,这种加载方式在加载执行完之前会阻止 onload 事件的触发,而现在很多页面的代码都在 onload 时还要执行额外的渲染工作等,所以还是会阻塞部分页面的初始化处理。

3. onload 时的异步加载

(function() { function async_load(){ var s = document.createElement('script'); s.type = 'text/javascript'; s.async = true; s.src = 'http://yourdomain.com/script.js'; var x = document.getElementsByTagName('script')[0]; x.parentNode.insertBefore(s, x); } if (window.attachEvent) window.attachEvent('onload', async_load); else window.addEventListener('load', async_load, false); })();

这和前面的方式差不多,但关键是它不是立即开始异步加载 js ,而是在 onload 时才开始异步加载。这样就解决了阻塞 onload 事件触发的问题。
补充:DOMContentLoaded 与 OnLoad 事件
DOMContentLoaded : 页面(document)已经解析完成,页面中的dom元素已经可用。但是页面中引用的图片、subframe可能还没有加载完。
OnLoad:页面的所有资源都加载完毕(包括图片)。浏览器的载入进度在这时才停止。
这两个时间点将页面加载的timeline分成了三个阶段。
4.异步加载的其它方法
由于Javascript的动态特性,还有很多异步加载方法:
XHR Eval
XHR Injection
Script in Iframe
Script Defer
document.write Script Tag
还有一种方法是用 setTimeout 延迟0秒 与 其它方法组合。
XHR Eval :通过 ajax 获取js的内容,然后 eval 执行。
var xhrObj = getXHRObject(); xhrObj.onreadystatechange = function() { if ( xhrObj.readyState != 4 ) return; eval(xhrObj.responseText); }; xhrObj.open('GET', 'A.js', true); xhrObj.send('');

Script in Iframe:创建并插入一个iframe元素,让其异步执行 js 。
var iframe = document.createElement('iframe'); document.body.appendChild(iframe); var doc = iframe.contentWindow.document; doc.open().write('<body onload="insertJS()">'); doc.close();

GMail Mobile:页内 js 的内容被注释,所以不会执行,然后在需要的时候,获取script元素中 text 内容,去掉注释后 eval 执行。
<script type="text/javascript"> /* var ... */ </script>

详见参考资料中2010年的Velocity 大会 Steve Souders 和淘宝的那两个讲义。
二、async 和 defer 属性
1. defer 属性
<script src="file.js" defer></script>

defer属性声明这个脚本中将不会有 document.write 或 dom 修改。
浏览器将会并行下载 file.js 和其它有 defer 属性的script,而不会阻塞页面后续处理。
defer属性在IE 4.0中就实现了,超过13年了!Firefox 从 3.5 开始支持defer属性 。
注:所有的defer 脚本保证是按顺序依次执行的。
2. async 属性
<script src="file.js" async></script>

async属性是HTML5新增的。作用和defer类似,但是它将在下载后尽快执行,不能保证脚本会按顺序执行。它们将在onload 事件之前完成。
Firefox 3.6、Opera 10.5、IE 9 和 最新的Chrome 和 Safari 都支持 async 属性。可以同时使用 async 和 defer,这样IE 4之后的所有 IE 都支持异步加载。
3. 详细解释
<script> 标签在 HTML 4.01 与 HTML5 的区别:
type 属性在HTML 4中是必须的,在HTML5中是可选的。
async 属性是HTML5中新增的。
个别属性(xml:space)在HTML5中不支持。
说明:
没有 async 属性,script 将立即获取(下载)并执行,然后才继续后面的处理,这期间阻塞了浏览器的后续处理。
如果有 async 属性,那么 script 将被异步下载并执行,同时浏览器继续后续的处理。
HTML4中就有了defer属性,它提示浏览器这个 script 不会产生任何文档元素(没有document.write),因此浏览器会继续后续处理和渲染。
如果没有 async 属性 但是有 defer 属性,那么script 将在页面parse之后执行。
如果同时设置了二者,那么 defer 属性主要是为了让不支持 async 属性的老浏览器按照原来的 defer 方式处理,而不是同步方式。
另参见官方说明:script async
个人补充:
既然 HTML5 中已经支持异步加载,为什么还要使用前面推荐的那种麻烦(动态创建 script 元素)的方式?
答:为了兼容尚不支持 async 老浏览器。如果将来所有浏览器都支持了,那么直接在script中加上async 属性是最简单的方式。
声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
中美有什么经济冲突 杨凌衡水实验中学高中学费是多少 蒂芙尼珍珠项链怎么清洗和保养? tiffany&amp;co 的缺点 如何保养蒂芙尼的项链? tiffany保养要多久时间 Tiffany珠宝需要多长时间保养? 人为什么活着,怎样活着都是无憾!! 孩子犟的不行家长怎么教育 有什么比较好用的游戏视频录制软件? 适用于Windows的10个好用的游戏录制软件 ps怎么去掉衣服褶皱? 傅天琳的《母亲》150左右赏析 javascript 中 匿名函数后面括号中函数怎么调用 是什么意思? (functio... js匿名函数与普通定义的函数有什么区别 阅读下面的诗歌,完成诗后问题。       秋雨声声      傅天琳窗外的雨声,淅淅沥沥 傅天琳的《柠檬黄了》内容是什么? 现代诗母亲作者傅天琳出自于哪里? 傅天琳的《柠檬黄了》 求傅天琳的诗歌大海 、 急用 谢谢啦 虚拟机终端怎么查看线程数 魅蓝六怎么插手机内存卡。 魅蓝note6可不可以换内存 魅蓝6无法访问外扩展内存怎么办? 魅蓝s6怎样扩充内存 《春》这篇短文的赏析以及阅读答案 《春天》阅读理解答案 踏着春天的脚印阅读答案艾伦为什么w总跟着妈妈呢用短文回答 《春天》阅读题答案 1、第二段文字中作者描绘了哪几幅春之图? 《春天》的阅读答案,文章和问题在下面,自己看吧,选上30分! 朱自清的《春》的阅读题答案是什么? 寻找现代朦胧派的短诗 js:在事件中调用匿名函数和直接调用函数的区别 傅天琳我是男子汉写作背景 ps去皱纹最好的方法 javascript中: (function(){})();如何理解? 写母亲的诗歌有哪些? js匿名函数自执行问题? javascript中的匿名函数是怎么被调用的,有几种方法 定义并且立即执行JS匿名函数有几种方法转 鲁迅、冯骥才、张海迪、郭沫若、哈瑞`马丁松、钱万成、傅天琳、邵燕祥的资料,快!!!!!!!! 傅天琳诗歌母亲是什么形象 关于母爱和父爱的现代诗马上!!!谢谢!!!作文需要!!! 人身意外保险赔付标准 人身意外伤害险赔付的问题 人身意外保险怎么陪付 人身意外伤害保险的赔偿问题 意外伤害赔偿:给员工上了意外险,保险公司不能全额赔付,那么未赔付的医疗费可否由公司及受伤员工分摊。 意外险赔偿医疗费吗? 人生意外险在投保期间,保费没交完的情况下,被保人受到意外伤害,保险公司会赔付吗 头发打蜡大概多长时间打一次阿?