0. 引入:
问题:全局声明的函数,始终都在GO里,不释放,随时随地都能调用
需求:函数立即执行,执行完成后立即释放
解决:
立即执行函数 IIFE - immediately invoked function expression
功能上又称 初始化函数
1. 写法:
// 写法1 - 使用更多
(function() {})();
// 写法2 - W3C建议
(function() {}());
1.1 示例: 立即执行函数 返回值 赋给变量
var num = (function(a, b){
return a + b;
})(1, 2);
console.log(num);
2. 深入理解:
2.1 (函数声明)() -> 能执行(立即执行函数)
(function(){
console.log(1) ;
})();
2.2 var a = 函数声明() -> 能执行
var test = function(){
console.log(1) ;
}();
2.3 函数声明() -> 语法错误
function(){
console.log(1) ;
}();
原因:
-
2.4 函数声明(参数) -> 无语法错误,函数未执行
function test(a, b){
console.log(a + b +1)
}(6, 10) // 10
原因:
为避免报错,JS引擎不把(6,10)理解为执行符号,而理解为逗号运算表达式
- ()内没有内容时,只能理解为执行符号,故而会报错
逗号运算,返回逗号最后一个值
function test(a, b){
console.log(a + b +1)
} // 函数声明
(6, 10) // 逗号运算 -> 10
2.5 + - ! && || 函数声明() -> 能执行
1 && function(){
console.log(1) ;
}();
说明: 将函数声明变成表达式的方法
() 包裹
console.log(test); // Uncaught ReferenceError: test is not defined
<a name="PTJvz"></a>
### 3. 面试题
<a name="JqxFn"></a>
#### 3.1 下面代码的执行结果,原因,改写
```javascript
function test() {
var arr = [];
for(var i = 0; i < 10; i++){
arr[i] = function() {
document.write(i + ' ')
}
}
return arr;
}
var myArr = test();
for(var j = 0; j < 10; j++) {
myArr[j]();
}
执行结果:10 10 10 ... 10个10
原理:闭包
myArr[j] 函数的作用域链中保存了函数test 的 AO,因此打印 i = 10
改写,使其打印 0, 1, 2, 3, 4, 5, …
function test() {
var arr = [];
for(var i = 0; i < 10; i++) {
(function(j) {
arr[j] = function() {
document.write(j + ' ')
}
})(i)
}
return arr;
}
var myArr = test();
for(var j = 0; j < 10; j++) {
myArr[j]();
}
3.2 点击某个li,打印其下标
<body>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
</ul>
</body>
var oLis = document.querySelectorAll("li");
for(var i = 0; i < oLis.length; i++) {
(function(j) {
oLis[j].onclick = function () {
console.log(j);
}
})(i)
}
3.3 下面一段代码执行的结果
var fn = (
function test1() { return 1 },
function test2() { return '2' }
)();
console.log(typeof fn) // -> 'string'
3.4 下面一段代码执行的结果
var a = 10;
if(function b() {}) {
// !!function () {} === true -> 执行if中的语句
// 函数声明变成表达式后,函数名被忽略,所以b不存在
a += typeof(b);
}
console.log(a); // -> 10undefined
4. 作业
4.1 累加器
闭包实现,初始值为0,每执行一次+1
function fCounter() {
var num = 0;
return function() {
num ++;
console.log(num);
}
}
var counter = fCounter();
counter();
4.2 学生名单管理
一个班级,学生名字保存在一个数组里,两个方法写在函数中的一个对象中,第一个方法加入班级,第二个方法离开班级,每次加入或离开都需要打印新的学生名单
function fClassMana() {
var stuList = [];
var printStuList = function() {
var s = ""
for(var i = 0; i < stuList.length; i++) {
stuList[i] && (s += stuList[i] + ' ')
}
console.log(s)
}
var classMana = {
addStu: function(name) {
stuList.push(name);
printStuList();
},
removeStu: function(name) {
for(var i = 0; i < stuList.length; i++) {
if(stuList[i] === name) {
stuList[i] = undefined;
}
}
printStuList();
}
}
return classMana;
}
var classMana = fClassMana();
classMana.addStu("little N");
classMana.addStu("little T");
classMana.addStu("little S");
classMana.removeStu("little T");