1、何为闭包?有什么用?
闭包专业的解释:
闭包是有权访问另一个函数作用域的变量的函数。 简单的说,Javascript允许使用内部函数—即函数定义和函数表达式位于另一个函数的函数体内。而且,这些内部函数可以访问它们所在的外部函数中声明的所有局部变量、参数和声明的其他内部函数。当其中一个这样的内部函数在包含它们的外部函数之外被调用时,就会形成闭包。
但我相信初学者看到上面的解释绝对是一脸懵逼,闭包应该是大家在JavaScript的学习中所遇到的第一个理解起来相对复杂的概念。我们先用一个经典的BUG来引出为什么要使用闭包:
function power() {
var arr = [];
for (var i=1; i<=3; i++) {
arr.push(function () {
return i * i;
});
}
return arr;
}
var results = power();
var f1 = results[0];
var f2 = results[1];
var f3 = results[2];
按照我们正常的逻辑,所希望得到的结果应为:
f1(); //1
f2(); //4
f3(); //9
但实际上却是:
f1(); //16
f2(); //16
f3(); //16
为什么?
原因在于将result[0]
,result[1]
,result[2]
分别绑定给f1
,f2
,f3
时,绑定的仅仅是power()
函数,并未立即计算。当获取结果时(即f1()
),开始执行函数,此时的i
已经变成了4,故所有的结果均为16。
怎么办?
从上述分析可知,根源在于函数绑定时没有即时保存结果,所以我们添加立即执行函数and闭包,让每一次变量都单独赋值,且最终结果不会发生改变:
function power() {
var arr = [];
for (var i = 1; i <= 3; i++) {
arr.push((function (n) {
return function () {
return n * n;
}
})(i));
}
return arr;
}
var results = power();
var f1 = results[0];
var f2 = results[1];
var f3 = results[2];
这时,所得到的结果就是我们先前所期望的值。我们着重分析一下闭包的结构与特性:
- 函数中套用函数;
- 父函数的返回值为子函数;
- 子函数能调用父函数以及更加外层的变量;
- 外部亦能随意给子函数传递参数以实现功能;
- 当父函数返回子函数时,子函数所接收的变量与参数均被保存在其中。
有什么用?
由特性可以看出来,闭包可以调用并保存外部参数、变量,并且能够保证返回函数中变量的独立性。这就可以给我们封装功能,实现模块化提供了巨大的便利。由于JS没有私有函数这一个概念,我们可以用这种办法来模拟出私有函数,具体实现过程可以看第4题。
2、setTimeout 0 有什么作用
-
setTimeout(function(){},ms)
是延迟函数,其内部有两个参数,第一个参数为所需要实现的功能函数,第二个参数为延迟的毫秒数。 -
setInterval(function(){},ms)
是间隔函数,参数设置与setTimeout
一样,区别在于setTimeout
只会在延迟XX毫秒后执行一次函数,而setInterval
会在延迟XX毫秒后执行函数后继续在延迟XX毫秒执行函数,无限循环。
3、下面的代码输出多少?修改代码让fnArr[i]()
输出 i
。使用两种以上的方法
var fnArr = [];
for (var i = 0; i < 10; i ++) {
fnArr[i] = function(){
return i;
};
}
console.log( fnArr[3]() ); // 10
代码1:
var fnArr = [];
for (var i = 0; i < 10; i ++) {
fnArr[i] = (function (n){
return function () {
return n;
}
}(i));
}
console.log( fnArr[3]() );
代码2:
var fnArr = [];
for (var i = 0; i < 10; i ++) {
fnArr[i] = (function (){
var n=i;
return function () {
return n;
}
}());
}
console.log( fnArr[3]() );
4、使用闭包封装一个汽车对象,可以通过如下方式获取汽车状态
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 speeed = 0;
function setSpeed(n) {
speed = n;
return speed;
}
function accelerate() {
speed += 10;
return speed;
}
function decelerate() {
speed -= 20;
return speed;
}
function getSpeed() {
return speed;
}
function getStatus() {
if (speed > 0){
return "running";
}
if (speed == 0){
return "stop";
}
if (speed < 0){
return "error!";
}
}
return {
accelerate: accelerate,
decelerate: decelerate,
getSpeed: getSpeed,
getStatus: getStatus,
setSpeed: setSpeed
};
}());
5、写一个函数使用setTimeout
模拟setInterval
的功能
var i = 0;
function intv(){
clock = setTimeout(function(){
console.log(i++);
intv();
},1000);
}
function stop(){
clearTimeout(clock);
}
intv();
6、写一个函数,计算setTimeout最小时间粒度
function getMini(){
var start = new Date().getTime();
var i = 0;
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);
}
getMini();
7、下面这段代码输出结果是? 为什么?
var a = 1;
setTimeout(function(){
a = 2;
console.log(a);
}, 0);
var a ;
console.log(a);
a = 3;
console.log(a);
依次输出 1,3,2.setTimeout函数的优先级最低,会放在程序最后执行,故实际上代码应该是:
var a;
a = 1 ;
console.log(a);
a = 3;
console.log(a);
setTimeout(function(){
a = 2;
console.log(a);
}, 0);
8、下面这段代码输出结果是? 为什么?
var flag = true;
setTimeout(function(){
flag = false;
},0)
while(flag){}
console.log(flag);
什么都输出不了进入死循环,代码其实是这样的:
var flag = true;
while(flag){}
console.log(flag);
setTimeout(function(){
flag = false;
},0)
9、下面这段代码输出?如何输出delayer: 0, delayer:1...(使用闭包来实现)
for(var i=0;i<5;i++){
setTimeout(function(){
console.log('delayer:' + i );
}, 0);
console.log(i);
}
setTimeout优先级最低,故先出0,1,2,3,4五个console.log(i)
的值,循环完毕i=5
,故输出5个delayer: 5;
闭包实现需求:
for(var i=0;i<5;i++){
setTimeout((function(i){
return function(){
console.log('delayer:' + i );
}
})(i), 0);
console.log(i);
}
网友评论