问题
什么是闭包? 有什么作用
闭包可以用来读取函数内部的变量。
function f1() {
var n = 999;
function f2() {
console.log(n);
}
return f2;
}
var result = f1();
result(); //999
由于作用域链表,外部是无法读取到函数内部的变量的。所以如果想要得到函数内部的变量,可以在函数体内部再定义一个函数,这个用这个函数返回所需要的变量。
function create_counter(initial) {
var x = initial || 0;
return { inc: function () {
x += 1;
return x;
}
}}
var c1 = create_counter();
c1.inc(); // 1
c1.inc(); // 2
c1.inc(); // 3
var c2 = create_counter(10);
c2.inc(); // 11
c2.inc(); // 12
c2.inc(); // 13
- 上面例子中,c1,c2引用的外部函数的x,是独立的两个值,封闭的包装。
- 闭包可以理解为是携带状态的函数,并且它的状态可以完全对外隐藏起来。
setTimeout 0 有什么作用
setTimeout(f, 0) ; 将第二个参数设为 0,作用是让 f 在现有的任务(脚本的同步任务和“消息队列”指定的任务)一结束就立刻执行。也就是说,setTimeout(f, 0)的作用是,尽可能早地执行指定的任务,而并不是会立刻就执行这个任务。
- 可以用于调整事件的发生顺序;
- 将一些消耗性能的任务,分成小块放到setTimeout(f, 0)中,可以减轻性能压力。
代码题
下面的代码输出多少?修改代码让fnArr[i]()
输出 i。使用两种以上的方法
var fnArr = [];
for (var i = 0; i < 10; i ++) {
fnArr[i] = function(){
return i;
};
}
console.log( fnArr[3]() ); //10
这段代码输出10。上段循环中,将一个函数,依次写进一个数组中,而这个函数不是立即执行的,通过fnArr[]()
调用,才进行执行。所以当循环结束后,此时i的数值已经变化为10,当调用fnArr[3]()
,实际上执行的是return i ;
,而此时的 i 就是 10。
var fnArr = [];
for (var i = 0; i < 10; i ++) {
fnArr[i] = (function (n){
return function (){
return n;
};
})(i);
}
console.log( fnArr[3]() ); //3
var fnArr = [];
for (var i = 0; i < 10; i ++) {
fnArr[i] = function fn(){
return fn.id;
};
fnArr[i].id = i;
}
console.log( fnArr[5]() ); //5
使用闭包封装一个汽车对象,可以通过如下方式获取汽车状态
function car(){
var speed = 0;
return {
setSpeed:function(val){
speed = val;
return speed;
},
getSpeed:function(){
console.log(speed);
return speed;
},
accelerate:function(){
speed += 10;
},
decelerate:function(){
speed -= 10;
if (speed < 0){
speed = 0;
}
},
getStatus:function(){
if(speed!==0){
console.log('running');
return 'running';
}
else {
console.log('stoped');
return 'stoped';
}
}
};
}
var Car = car();
Car.setSpeed(30);
Car.getSpeed(); //30
Car.accelerate();
Car.getSpeed(); //40;
Car.decelerate();
Car.decelerate();
Car.getSpeed(); //20
Car.getStatus(); // 'running';
Car.decelerate();
Car.decelerate();
Car.getStatus(); //'stop';
//Car.speed; //undefined;
写一个函数使用setTimeout模拟setInterval的功能
var i = 0;
function interval(){
setTimeout(function(){
console.log(i++);
interval();
},1000);
}
interval();
写一个函数,计算setTimeout最小时间粒度
function getMini(){
var i = 0;
var start = Date.now();
var timer = setTimeout(function(){
i++;
if(i === 1000){
clearTimeout(timer);
var end = Date.now();
console.log((end-start)/i);
}
timer = setTimeout(arguments.callee,0);
},0);
}
getMini();//4.112//4.117
下面这段代码输出结果是? 为什么?
var a = 1;
setTimeout(function(){
a = 2;
console.log(a);//3执行
}, 0);
var a ;
console.log(a); //1执行
a = 3;
console.log(a);//2执行
//1 3 2
-
setTimeout(func,0)
会将任务在下一个Event Loop之前执行,所以这里的function被移到了最后进行执行。
下面这段代码输出结果是? 为什么?
var flag = true;
setTimeout(function(){
flag = false;
},0);//理论上不会执行
while(flag){}
console.log(flag);//理论上不会执行
- setTimeout将function移到下一个Event Loop之前执行,但是while将这个阻断了,陷入了无限循环。所以flag不能被赋值成false。这也说明程序的运行是单线程的。
下面这段代码输出?如何输出delayer: 0, delayer:1...(使用闭包来实现)
for(var i=0;i<5;i++){
setTimeout(function(){
console.log('delayer:' + i );
}, 0);
console.log(i);
}
-----------
for(var i=0;i<5;i++){
(function(num){
setTimeout(function(){
console.log('delayer:' + num );
}, 0);
})(i);
console.log(i);
}
本教程版权归 张宇 及 饥人谷 所有,转载请标明出处。