应用1:创建临时独立作用域
假设想创建一个累加器这样的功能,需要一个临时变量用于保存累加状态。放在全局作用域显然不太优雅,最简单的方法就是创建一个IIFE(立即执行函数)然后创建变量,返回一个函数,然后再函数中完成累加功能。
// 以前
var n= 0
setInterval(() => console.log(++n), 1000)
复制代码
// 现在
setInterval((function() {
var n = 0
return function() {
console.log(++n)
}
})(), 1000)
复制代码
应用2:解决变量名冲突
利用参数优先全局变量的规则,可以让函数内部的小环境内限制作用域变量名称。
比如: jquery会使用全局的,但是其他库也有可能使用, 但是其他库也有可能使用,但是其他库也有可能使用这个函数名,这样就会造成函数名冲突。
假定我们有大量存量代码使用$这个函数名调用jquery,我们不太可能全部改写这个代码。这时候其实使用即时函数就可以很好的解决这个问题。
<script src="https://lib.baomitu.com/jquery/3.6.0/jquery.min.js"></script>
<script>
// 假设其他库占用的$
const $ = () => console.log("Not jQuery");
// 闭包限制当前作用域的$
(function ($) {
$(document).ready(function () {
console.log("Hello jQuery");
});
})(jQuery);
$()
</script>
复制代码
应用3:使用简洁变量名
第三个场景类似with这个功能
// with主要是用来对对象取值的(复杂结构with影响性能),如下所示:
with(obj) {
var newa = a;
var newb = b;
console.log(newa+newb);
}
该语句 等价于:
var newa = obj.a;
var newb = obj.b;
console.log(newa+newb);
复制代码
// 一个复杂的变量
var data {
abc : {
efg : 0
}
}
(function() {
console.log(v)
})(data.abc.efg)
复制代码
现在有了解构赋值,这一个场景作用不大了。
应用4:循环陷阱
作为Javascript面试题八大陷阱题之一,我们下面看看循环陷阱是如何解决的。
循环内加入即时函数,由于即时函数的参数为实参复制关系,相当于复制的现场快照
const ary = [];
for (var i = 0; i < 5; i++) {
(function(n) {·
ary.push(function () {
return console.log(n);
});
})(i)
}
ary[0]();
ary[1]();
复制代码
应用5:类库封装
类库封装最重要的要求就是不能让类库中的变量污染全局。 比如jQuery只暴露 $ 就好了
封装1:
(function () {
var jQuery = window.$ = function() {
// initialize
}
})()
复制代码
- jQuery构造器(匿名函数)赋值给window.$ 作为全局变量
- 为了保证其他代码改变或删除jQuery变量 , 所以声明一个局部变量jQuery, 保证jQuery代码内都可以使用jQuery这个名字。
封装2:
var $ = (
function() {
function jQuery() { // Initialize }
return jQuery
}
)()
复制代码
应用6:webpack打包模块
A模块 a.js
// a.js
const time = Date.now()
module.exports = 'A:' + time
复制代码
复制代码
入口index.js
// index.js
const a = require("./a");
console.log(a);
复制代码
复制代码
运行webpack打包
npx webpack
复制代码
复制代码
- 整体使用自运行函数 – 任何变量不污染全局
- 变量 o 为模块集合
var o = { // 原来的a.js 85: (o) => { const r = Date.now(); o.exports = "A:" + r; },},复制代码
- t函数为exports、require模拟函数
- r = {}; // 模拟exports对象 function t(e) { // 模拟require函数 var n = r[e]; if (void 0 !== n) return n.exports; var s = (r[e] = { exports: {} }); return o[e](s, s.exports, t), s.exports; } 复制代码
- 入口为自执行函数 引用o 、t变量形成闭包
- (() => { const o = t(85); console.log(o); })(); 复制代码 复制代码
- 由于t函数是变量提升的所以require函数也可以在子模块里调用 – 这个大家可以自己实验一下。
应用7:惰性函数
惰性函数表示函数执行的分支只会在函数第一次调用的时候执行,在第一次调用过程中,该函数会被覆盖为另一个按照合适方式执行的函数,这样任何对原函数的调用就不用再经过执行的分支了。
7.1 实现计算缓存
var square = (function (){
// 注意cache限制大小
var cache = {}
return function(n){
return (cache[n] = n * n)
}
})()
复制代码
7.2 单例模式缓存
实现方法一般是先判断实例是否存在,如果存在就直接返回,否则就创建了再返回。单例模式的好处就是避免了重复实例化带来的内存开销。 就是避免了重复实例化带来的内存开销。
// 单例模式
function Singleton(){
this.data = 'singleton';
}
Singleton.getInstance = (function () {
var instance;
return function(){
if (instance) {
return instance;
} else {
// 缓存实例
instance = new Singleton();
return instance;
}
}
})();
var sa = Singleton.getInstance();
var sb = Singleton.getInstance();
console.log(sa === sb); // true
console.log(sa.data); // 'singleton'
复制代码
单例模式前端最典型的应用场景,全局唯一消息框。
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.model {
width: 200px;
height: 200px;
border: 1px solid aqua;
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
text-align: center;
}
</style>
</head>
<body>
<div id="loginBtn">点我</div>
<script>
// 惰性函数
var getSingle = function (fn) {
var result;
return function () {
//没有缓存
return result || (result = fn.apply(this, arguments))
}
}
// 创建dom对象
var createLoginLayer = function () {
var oDiv = document.createElement("div");
oDiv.innerHTML = "我是登录浮窗";
oDiv.className = "model";
oDiv.style.display = "none";
document.body.appendChild(oDiv);
return oDiv;
}
var createSingleLoginLayer = getSingle(createLoginLayer);
document.getElementById("loginBtn").onclick = function () {
//动态创建弹窗
//新建一个弹窗实例,内部使用单例模式管理,一直只能有一个.
var loginLayer = createSingleLoginLayer();
loginLayer.style.display = "block"
}
</script>
</body>
复制代码
7.3 提高浏览器兼容问题的执行效率
bom api兼容
function addEvent(type, element, fun) {
if (element.addEventListener) {
addEvent = function (type, element, fun) {
element.addEventListener(type, fun, false);
}
}
else if (element.attachEvent) {
addEvent = function (type, element, fun) {
element.attachEvent('on' + type, fun);
}
}
else {
addEvent = function (type, element, fun) {
element['on' + type] = fun;
}
}
return addEvent(type, element, fun);
}
复制代码
ajax兼容
function createXHR() {
var xhr = null;
if (typeof XMLHttpRequest != "undefined") {
xhr = new XMLHttpRequest();
createXHR = function () {
return new XMLHttpRequest();
};
} else {
try {
xhr = new ActiveXObject("Msxml2.XMLHTTP");
createXHR = function () {
return new ActiveXObject("Msxml2.XMLHTTP");
};
} catch (e) {
try {
xhr = new ActiveXObject("Microsoft.XMLHTTP");
createXHR = function () {
return new ActiveXObject("Microsoft.XMLHTTP");
};
} catch (e) {
createXHR = function () {
return null;
};
}
}
}
return xhr;
}
复制代码
应用8:函数颗粒化
应用9:hooks
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://itzsg.com/10254.html