立即执行函数
视频地址:
立即执行函数(IIFE) == `Immediately Invoked Function Expression`
// 函数声明 !== 函数表达式 function test1 () { console.log('Function Declaration'); } // 把一个(匿名)函数(函数声明式)赋值给一个变量的形式 var test2 = function () { console.log("Function Expression"); } // 对于函数名后边的括号,叫做执行符号 test1() test2() // 语法错误:执行符号只能跟在表达式后边 function test3 () { console.log('Function Declaration'); }()
当一个函数是需要立即执行时,必须是表达式形式
var fn =(function () { console.log('Function Expression'); })(); // 或者(任何运算都是表达式) +(function () { console.log('Function Expression'); })(); ( // W3C推荐的立即执行函数的规范 (function () { console.log('Function Expression'); })() ); // 实践中 (function () { console.log('Function Expression'); })();
(function test(a, b, c, d) { /** * 1. 可以创建一个与外界没有任何关系的作用域,独立作用域 * 2. 执行完立即销毁 * ES3 ES5 没有模块的概念,立即执行函数来模拟模块化 * 向外部抛出一系列属性和方法 * window上保存的属性和方法 */ console.log(test); console.log(test.length); console.log(arguments.length); console.log('hello'); })(1, 2, 3); // test() // 抱错—— 外部无法得到这个函数
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Documenttitle>
<style>
#my-tab {
width: 500px;
height: 500px;
border: 1px solid #000;
margin: 50px auto;
}
.tab-wrapper {
height: 50px;
border-bottom: 1px solid #000;
}
.tab-item {
float: left;
width: 33.33%;
height: 50px;
text-align: center;
line-height: 50px;
}
.tab-item.current {
background-color: #000;
color: #fff;
}
.page-wrapper {
position: relative;
height: 450px;
}
.page-item {
display: none;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 450px;
text-align: center;
line-height: 450px;
}
.page-item.current {
display: block;
}
style>
head>
<body>
<div
id="my-tab"
data-type='[
{
"tab": "选项一",
"page": "页面1"
},
{
"tab": "选项二",
"page": "页面2"
},
{
"tab": "选项三",
"page": "页面3"
}
]'
>div>
<script src="./utils.js">script>
<script src="./tpl.js">script>
<script src="./index.js">script>
<script>
new MyTab('#my-tab');
script>
body>
html>
utils.js
var tools = (function () { function tplReplace (tpl, replaceObj) { return tpl.replace(/\{\{(.*?)\}\}/g, function (node, key) { return replaceObj[key.trim()] }) } return { tplReplace: tplReplace } })()
tpl.js
var tpl = (function () { function tab (field) { switch (field) { case 'tab': return ( `{{ tab }}` ) case 'page': return ( `{{ page }}` ) default: break; } } return { tab: tab } })()
index.js
; (function (doc, tpl, tools) { // 定义MyTabl方法 function MyTab (el) { // 获取元素 this.el = doc.querySelector(el); // 获取元素数组 this.data = JSON.parse(this.el.getAttribute("data-type")); // 设置默认展示第一个 this._index = 0; // 初始化方法 this.init() } MyTab.prototype.init = function () { // 渲染页面 this._render() // 绑定方法 this._bindEvent() } // 渲染页面 MyTab.prototype._render = function () { // 创建 tab 元素 var tabWrapper = doc.createElement('div') // 创建 page 元素 var pageWrapper = doc.createElement('div') // 为了避免多次将节点插入document,采用 Fragment var oFrag = doc.createDocumentFragment() // 定义默认类名 tabWrapper.className = 'tab-wrapper' pageWrapper.className = 'page-wrapper' // 遍历标签data this.data.forEach(function (item, index) { // 将 模板内的元素,替换为 this.data 的数据 tabWrapper.innerHTML += tools.tplReplace(tpl.tab('tab'), { tab: item.tab, current: !index ? 'current' : '' }) pageWrapper.innerHTML += tools.tplReplace(tpl.tab('page'), { page: item.page, current: !index ? 'current' : '' }) }) // 将 html 代码片段添加到 fragment oFrag.appendChild(tabWrapper) oFrag.appendChild(pageWrapper) // 将 fragment 挂载到页面上 this.el.appendChild(oFrag) } // 为每一个 tab 绑定方法 MyTab.prototype._bindEvent = function () { // 获取 tab 和 page 的所有元素 var doms = { oTabItems: doc.querySelectorAll('.tab-item'), oPageItems: doc.querySelectorAll('.page-item'), } // 绑定点击事件 注意: 此时bind后的 this 是指向当前的el元素 this.el.addEventListener('click', this._handlerTabClick.bind(this, doms)) } MyTab.prototype._handlerTabClick = function () { // 获取 tab/page 所有元素、点击的元素、以及点击元素的类名 var _doms = arguments[0], tar = arguments[1].target, className = tar.className.trim(); // 判断点击元素,如果没有 current 类名,则更新视图 if (className === 'tab-item') { // 给原来激活的元素重置类名 _doms.oTabItems[this._index].className = 'tab-item'; _doms.oPageItems[this._index].className = 'page-item'; // 获取最新激活的元素索引 this._index = [].indexOf.call(_doms.oTabItems, tar); // 给点击的tab元素添加 current 类 tar.className += ' current'; // 给点击的tab对应的 page 添加 current 类 _doms.oPageItems[this._index].className += ' current'; } } window.MyTab = MyTab })(document, tpl, tools)