for(var i = 0;i < 10;i++){
}
console.log(i);
课前准备:上面这个函数的输出结果是10,因为当i == 10的时候,不满足函数循环的条件,退出循环。
正式例题
function test(){
var arr = [];
for(var i = 0;i < 10;i++){
arr[i] = function (){
document.write(i+' ');
}
}
return arr;
}
var arr = test();
for(var j = 0; j < 10;j++){
arr[j]();
}
解析:此时打印出来的是10个10,10个很容易理解,因为for循环执行了10次,但是,为什么是10呢?为什么不是1,2,3,4,5,6,7,8,9,呢?因为在
arr[i] = function (){
console.log(i);
}
的时候,仅仅是arr[]数组中德项数被赋值为函数,该函数并没有被立刻执行,(如果想立即执行,可以在后面加上括号),在下面for循环执行的时候,i的值已经像最初的引言函数中的那样,i的值已经变成10。
解决方案
问题描述:上面的问题是我想输出0,1,2,3,4,5,6,7,8,9,可是现在输出的却是10个10,解决方案目前来看有且仅有一种。
function test(){
var arr = [];
for(var i = 0;i < 10;i++){
(function(j){ //注意此时的改变
arr[j] = function (){
console.log(i);
}
}(i))
}
return arr;
}
var arr = test();
for(var j = 0; j < 10;j++){
arr[j]();
}
解析:立即执行函数会每次执行完之后销毁,每个j与每个立即执行函数function具有一一对应的关系,每个 function (){
console.log(i);
}保存相对应外部立即执行函数的劳动成果,在这里形成了闭包,内部函数被保存到了外部。
思想:利用立即执行函数闭包解决外部闭包
闭包的作用
- 实现公有变量(比如说累加器,但是不借助外部变量)
如果借助于外部变量的实现方式:
var count = 0 ;
function test(){
count++;
console.log(count);
}
test();
test();
test();
test();
test();
test();
使用闭包实现:
function add(){
var count = 0;
function a(){
console.log(++count);
}
return a;
}
var demo = add();
demo();
demo();
- 作为缓存(存储结构)
function test(){
var food = 'apple';
var obj = {
eat: function(){
if(food != ''){
console.log('i am eating '+ food);
food = '';
}else{
console.log('There is nothing!')
}
},
push: function(myfood){
food = myfood;
}
}
return obj;
}
var person = test();
person.eat();
person.eat();
person.push('banana');
person.eat();
- 可以实现封装,属性私有化。
- 模块化开发,防治污染全局变量。
var test = function(){
console.log('a');
}();
console.log(test);
解析:后面打印test的时候,此时test不代表一个函数,表达式()执行之后,相当于这个样子
var test; console.log(test);
所以打印结果是undefined。
只有表达式才能被执行,函数声明不能被执行。
function(){
…代码块
}()
上面代码会报错,声明不能被执行,但是如果在前面加上一个+号或者减号通过隐式类型转化变成表达式就可以执行。
笔试题
var f = (
function f(){
return '1';
},
function g(){
return 1;
}
)();
console.log(typeof f);
能否抽象出来(a++,++a)逗号的运算法则是解决这个题目的关键。
非常有深度的一道题目
var x = 1;
if(function f(){}){
x += typeof f;
}
console.log(x);
输出:1undefined