网站首页 > 基础教程 正文
应用1:创建临时独立作用域
假设想创建一个累加器这样的功能,需要一个临时变量用于保存累加状态。放在全局作用域显然不太优雅,最简单的方法就是创建一个IIFE(立即执行函数)然后创建变量,返回一个函数,然后再函数中完成累加功能。
Bash
// 以前
var n= 0
setInterval(() => console.log(++n), 1000)
复制代码
Bash
// 现在
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
猜你喜欢
- 2024-10-12 面试常客系列之跨域 java跨域面试题
- 2024-10-12 如何根治 Script Error. 如何根治神经性皮炎
- 2024-10-12 只用一个js文件,为你的网站加个黑暗模式
- 2024-10-12 LLM工程师应该如何防范提示注入?指导来了
- 2024-10-12 如何实现前端社交媒体分享功能 前端聊天功能如何实现
- 2024-10-12 「WWDC2018」-Web安全策略 web安全进阶
- 2024-10-12 「JS库」3个很棒的小众JavaScript库
- 2024-10-12 如何使用 如何使用验孕棒
- 2024-10-12 2 JavaScript核心 script标签 营养标签中的核心营养素
- 2024-10-12 GitHub精选 | Feather一组简单漂亮的开源图标
- 最近发表
- 标签列表
-
- gitpush (61)
- pythonif (68)
- location.href (57)
- tail-f (57)
- pythonifelse (59)
- deletesql (62)
- c++模板 (62)
- css3动画 (57)
- c#event (59)
- linuxgzip (68)
- 字符串连接 (73)
- nginx配置文件详解 (61)
- html标签 (69)
- c++初始化列表 (64)
- exec命令 (59)
- canvasfilltext (58)
- mysqlinnodbmyisam区别 (63)
- arraylistadd (66)
- node教程 (59)
- console.table (62)
- c++time_t (58)
- phpcookie (58)
- mysqldatesub函数 (63)
- window10java环境变量设置 (66)
- c++虚函数和纯虚函数的区别 (66)