📌 立即执行函数IIFE(immediately invoked function expression)
立即执行函数 创建后立即执行,本质是函数表达式
- 页面加载自动执行,执行完成立即销毁(故忽略函数名) ```javascript //第一种写法——————————— (function(){ … })();
//第二种写法【W3C建议写法】——————————- (function(){ … }());
**函数**只要**以表达式形式**出现,无论**有名与否**,无论**执行与否**,其**自动忽略函数名**,通过函数名**调用会报错**,typeof检测**类型为undefined **
> **注意:错误写法——报语法错误**
> ** Uncaught SyntaxError: Unexpected token ")" **
```javascript
//错误的写法
function (){
...
}(); //报错: Uncaught SyntaxError: Unexpected token (
- 错误原因
- 一定是表达式才能被执行符号执行
- 语句后的()会被当做分组操作符,分组操作符里不能未空必须有表达式,所以报错
- 即使()内有值或表达式,JavaScript引擎会将其当作单独的表达式来解析,不报错,函数因未被调用而不会执行
- 因其执行完成立即销毁,所以立即执行函数忽略函数名(在其外部使用函数名调用报错未定义)
//让Javascript引擎认为这是一个表达式的方法还有很多
!function(){}();
+function(){}();
-function(){}();
~function(){}();
0 || function(){}();
1 && function(){}();
new function(){ /* code */ }
new function(){ /* code */ }() // 只有传递参数时,才需要最后那个圆括号
- 一定是表达式才能被执行符号执行
经典实用场景案例 利用立即执行函数弹出对应事件索引
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>利用立即执行函数弹出对应事件索引</title>
</head>
<body>
<ul>
<li>点击,打印0</li>
<li>点击,打印1</li>
<li>点击,打印2</li>
<li>点击,打印3</li>
<li>点击,打印4</li>
</ul>
<script>
var lis = document.querySelectorAll("li")
for (var i = 0; i < lis.length; i++) {
(function (j) {
lis[j].addEventListener('click', function () {
console.log(j);
})
}(i))
}
</script>
</body>
</html>
立即执行函数 和 闭包 的区别 ? 两者经常会结合在一起使用,但其两者本质不同
- **共同点**:
- 可以减少全局变量的使用
- 不同点**:**
- 立即执行函数:声明之后立即执行,一般只调用一次后立即销毁,不占内存空间
- 闭包:让外部可以访问其内部作用域,保证内部变量安全,但其内部变量被引用无法销毁,增加了内存消耗,可能造成内存泄漏
📌 逗号运算符
逗号运算符 执行所有的操作数,只返回最后一个操作数的值 逗号运算符在JavaScript中的优先级是最低的
- 单一var声明模式,多个变量连续赋值 ```javascript var a = 1,b = 2,c = 3,d = 4;
// 等价于———————————————— var a = 1; var b = 2; var c = 3; var d = 4;
- **逗号运算符可用于赋值,返回表达式中的最后一项**
```javascript
var num = (1,2,3,4,5);
console.log(num); // 5
- 常用于for循环中,可循环多个变量
for(var i= 0,j = 10; i < j; i++, j--){
console.log(i + j) // 10 10 10 10 10
};
📋 课后作业
1、累加器,初始值0,利用闭包,执行闭包函数,每执行一次+1 2、缓存器,利用闭包,学生名保存在数组里,两个方法写在函数的对象中, 方法一功能加入班级,方法二功能离开班级,每次加入或离开都需答应班级人员新名单
// 累加器,初始值0,利用闭包,执行闭包函数,每执行一次+1
function accumulation() {
var init = 0;
return function () {
init++
console.log(init);
}
}
var add = accumulation()
add(); //1
add(); //2
add(); //3
add(); //4
add(); //5
-------------------------------------------------------------
/*
*缓存器,利用闭包,学生名保存在数组里,两个方法写在函数的对象中
*功能方法一加入班级,
*功能方法二离开班级,
*每次加入或离开都需打印班级人员新名单
*/
function cache() {
var students = [];
function add(newName) {
students.push(newName)
console.log('欢迎' + '【' + newName + '】' + '同学加入!' + '目前班级人员名单如下:');
for (var i = 0; i < students.length; i++) {
console.log(students[i]);
}
}
function leave(oldName) {
var idx = students.indexOf(oldName)
if (idx == -1) return console.log('----查无此人----');
students.splice(idx, 1)
console.log('送别' + '【' + oldName + '】' + '同学!' + '目前班级人员名单如下:');
if (students.length <= 0) return console.log('班级人数已经清0,目前已无人员信息');
for (var j = 0; j < students.length; j++) {
console.log(students[j]);
}
}
return { add, leave }
}
var res = cache()
res.add('张三') //欢迎【张三】同学加入!目前班级人员名单如下:张三
res.add('王五') //欢迎【王五】同学加入!目前班级人员名单如下:张三 王五
res.add('李四') //欢迎【李四】同学加入!目前班级人员名单如下:张三 王五 李四
res.leave('小李') //----查无此人----
res.leave('张三') //送别【张三】同学!目前班级人员名单如下:王五 李四
res.leave('李四') //送别【李四】同学!目前班级人员名单如下:王五
res.leave('王五') //送别【王五】同学!目前班级人员名单如下:班级人数已经清0,目前已无人员信息
res.leave('张三') //----查无此人----