问题
1.什么是闭包? 有什么作用
JavaScript高级程序设计第三版定义闭包是指有权访问另一个函数作用域中的变量的函数。
function f1() {
var n = 999;
function f2() {
console.log(n);
}
return f2;
}
var result = f1();
result(); // 999
上面代码中,函数f1的返回值就是函数f2,由于f2可以读取f1的内部变量,所以就可以在外部获得f1的内部变量了。闭包就是函数f2,即能够读取其他函数内部变量的函数。由于在JavaScript语言中,只有函数内部的子函数才能读取内部变量,因此可以把闭包简单理解成“定义在一个函数内部的函数”。闭包最大的特点,就是它可以“记住”诞生的环境,比如f2记住了它诞生的环境f1,所以从f2可以得到f1的内部变量。在本质上,闭包就是将函数内部和函数外部连接起来的一座桥梁。
作用:1.可以读取函数内部的变量;2.让这些变量始终保持在内存中
参考:闭包
2.setTimeout 0 有什么作用
setTimeout(f, 0)的作用是,尽可能早地执行指定的任务。而并不是会立刻就执行这个任务。setTimeout(f, 0)可以调整事件的发生顺序。比如,网页开发中,某个事件先发生在子元素,然后冒泡到父元素,即子元素的事件回调函数,会早于父元素的事件回调函数触发。如果,我们先让父元素的事件回调函数先发生,就要用到setTimeout(f, 0)。
参考:定时器
代码题
1.下面的代码输出多少?修改代码让fnArri 输出 i。使用两种以上的方法
var fnArr = [];
for (var i = 0; i < 10; i ++) {
fnArr[i] = function(){
return i;
};
}
console.log( fnArr[3]() );
- 方法一,赋值给立即执行函数,外部需要传递参数
var fnArr = [];
for (var i = 0; i<10; i++){
fnArr[i] = (function(i){
return function(){
return i
}
}(i))
}
console.log( fnArr[3]() );
- 方法二,赋值给立即执行函数,声明一个临时变量存储i的值,外部不需要传参。
var fnArr = [];
for (var i = 0; i<10; i++){
fnArr[i] = (function(n){
var n = i;
return function(){
return n
}
}())
}
console.log( fnArr[3]() );
- 方法三,把它绑定在函数上,作为函数的一部分,不需要通过闭包,得到函数就能得到值。
var fnArr = []
for (var i = 0; i < 10; i++) {
var fn = function() {
}
fn.idx = i
fnArr[i] = fn
}
console.log(fnArr[3].idx)
2.使用闭包封装一个汽车对象,可以通过如下方式获取汽车状态
var Car = //todo;
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; //error
实现代码如下:
var Car=(function (){
var speed = 0;
function setSpeed(num){
speed=num;
}
function getSpeed(){
console.log(speed)
}
function accelerate(){
speed + =10;
}
function decelerate(k){
speed - =10;
}
function getStatus(){
if(speed>0){
console.log('running')
}else{
console.log('stop')
}
}
return {
setSpeed:setSpeed,
getSpeed:getSpeed,
accelerate:accelerate,
decelerate:decelerate,
getStatus:getStatus
}
})();
输出结果如下:
3.写一个函数使用setTimeout模拟setInterval的功能
var i=0;
function intv(){
setTimeout(function(){
console.log(i++);
intv();
},1000)
}
输出结果如下:
4.写一个函数,计算setTimeout平均[备注:新加]最小时间粒度
function getMint(){
var i=0
var start = Date.now()
var clock = setTimeout(function(){
i++;
if(i=== 1000){
clearTimeout(clock)
var end = Date.now()
console.log((end-start)/i)
}
clock = setTimeout(arguments.callee,0)
},0)
}
5.下面这段代码输出结果是? 为什么?
var a = 1;
setTimeout(function(){
a = 2;
console.log(a);
}, 0);
var a ;
console.log(a);
a = 3;
console.log(a);
输出结果如下:
原因:必须要等到当前脚本的同步任务和“任务队列”中已有的事件,全部处理完以后,才会执行setTimeout指定的任务,所以最后输出2。
6.下面这段代码输出结果是? 为什么?
var flag = true;
setTimeout(function(){
flag = false;
},0)
while(flag){}
console.log(flag);
没有输出。因为while判断为真,flag为true,为死循环,setTimeout是执行完其他代码后才执行,所以无限循环,没有输出。
7.下面这段代码输出?如何输出delayer: 0, delayer:1...(使用闭包来实现)
for(var i=0;i<5;i++){
setTimeout(function(){
console.log('delayer:' + i );
}, 0);//setTimeout函数最后执行,此时i已经为5,for每循环一次,setTimeout都要执行一次,只不过它是等到所有的代码执行完了再执行,所以最后一共输出五个delayer: 5
console.log(i);//输出0,1,2,3,4
}
代码实现如下:
for(var i=0;i<5;i++){
(function(){
var n = i;
setTimeout(function(){
console.log('delayer:' + n );
}, 0);
console.log(n);
})();
}