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 下面代码的执行结果,原因,改写```javascriptfunction 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");
