1.立即执行函数
IIFE => immediately invoked function expression
写法2: w3c推荐写法 (function(){ }())
<a name="YhNDf"></a>
### ()包起来的,都是表达式,一定是表达式才能被执行
```javascript
(function(){
console.log(可以立即执行);
})()
function(){
}()
=> 理解成
function(){}
() 并不会立即执行
// 可以被执行,
var test = function(){
console.log(2);
}()
console.log(test); // undefined
1.2 可以携带参数
(function(a, b){
console.log(a + b); // 6
})(2, 4)
1.3 立即执行函数的返回值
var test = (function(a, b){
return a + b
})(2, 3)
console.log(test); // 5
var name = (function(name){
return name
})('bobo')
console.log(name); // bobo
1.4 函数可以立即执行的情况
1. 第一种
(function(){
console.log(1);
})()
2. 第二种
var test = fucntion(){
console.log(1);
}() // 可以执行,因为()之前为表达式
3.第三种
function test(){
console.log(1);
}() // 会报错
!() 内部不写, 会报错
function test(){
}('1') 传入会被当表达式,不会报错,不会执行
1.5 立即执行函数立即执行结束后,就会被销毁
var test = (function(){
console.log(1); // 1
})()
console.log(test);// undefined
// 打印 1 和 undefined 证明立即执行函数执行结束之后,立即被销毁了,
// 所以test是undefined
1.6 立即执行函数的函数名无意义,会自动被忽略,
var a = 10;
if(function b(){}){
a += typeof(b);
}
console.log(a); // '10undefined'
1.7 把函数声明变成表达式的方法 + - ! || && void
+function(){
console.log(1);
}() // 1
-function(){
console.log(1);
}() // 1
!function(){
console.log(1);
}() // 1
0 || function(){ // 隐式转换成fasle的都可以 undefined null false 0 ''
console.log(1);
}() // 1
1 && function(){ //隐式转换不是false的都可以
console.log(1);
}() // 1
void function(){
console.log(1);
}() // 1
2, 3, function(){
console.log(1);
}() // 1
2. ,逗号运算符
对它的每个操做数求值,从左到右,返回最后的值。
var num = (2, 3, 45, 767);
console.log(num);// 767
3.闭包深入
案例1: 打印0-9
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
// 方法1 => 立即执行函数
function test() {
for(var i = 0; i < 10; i++) {
(function() {
document.write(i + '');
})()
}
}
test();
// 方法2 在外边传入参数
function test() {
var arr = [];
for(var i = 0; i < 10; i++) {
arr[i] = function(num) {
document.write(num + '');
}
}
return arr;
}
var myArr = test();
for(var j = 0; j < 10; j++) {
myArr[j](j);
}
// 方法3 将其在函数内部进行保存
function test() {
var arr = [];
for(var i = 0; i < 10; i++) {
(function(j){
arr[j] = function(j){
document.write(j + ' ');
}
})(i)
}
return arr;
}
var myArr = test();
for(var j = 0; j < 10; j++) {
myArr[j]();
}
案例2: 点击事件打印
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
</ul>
<script type="text/javascript">
var oLi = document.querySelectorAll('li');
console.log(oLi);
for(var i = 0; i < oLi.length; i++){
(function(j){
oLi[j].onclick = function(){
console.log(j);
}
})(i)
}
</script>
4.面试
function test(a){
console.log(a);// 不会执行
}(6) // (6) 被当成了表达式,而不是立即执行符号
test(1);// 打印输出 1
var fn = (
function test1(){
return 1
},
function test2(){
return '2'
}
)();
console.log(fn);// '2'
console.log(typeof(fn));// string
var a = 10;
// ! (function b(){}) => 表达式,函数名称被忽略, => undefined
if(function b(){}){
a += typeof(b);
}
console.log(a); // 10undefined
5.练习
1. 累加器,初始值为0,写个闭包,执行一次函数加1打印
function accu(){
var i = 0;
return function add(){
// i++;
// console.log(i);
console.log(++i);
}
}
var accu1 = accu();
accu1();
accu1();
accu1();
2. 缓存器:
缓存器 : 一个班级,学生名保存在一个数组,俩个方法写在函数中的一个对象中,
第一个方法,加入班级,第二个方法离开班级
每次加入或离开,都需要打印新的学生名单
function buffer(){
var studentsArr = ['小明','小红'];
var operStd = {
join:function(name){
studentsArr.push(name);
console.log(studentsArr);
// for(var i = 0; i < studentsArr.length; i++){
// (function(){
// console.log(studentsArr[i]);
// })()
// }
},
quit: function(name){
var index = studentsArr.indexOf(name);
// console.log(index);
if(index !== -1){
studentsArr.splice(index,1);
}
console.log(studentsArr);
// for(var i = 0; i < studentsArr.length; i++){
// var item = studentsArr[i]; // ? for循环型性能 的优化
// if(item === name){
// studentsArr.splice(i);
// }
// }
}
};
return operStd
}
var operStd = buffer();
operStd.join('小阿飞');
operStd.quit('小红');