小白滴认知
来源:互联网 发布:java代码 编辑:程序博客网 时间:2024/06/06 02:37
小白遇到的面试题:
for (var i = 0; i < 3; i++) {
setTimeout(function() {console.log(i);
}, 0);
console.log(i);
}
输出的结果是0,1,2,3,3,3
分析本题:
(1)先理解本质
setTimeout(function() {
console.log(1);
}, 0);
console.log(2);
此时先输出2,再输出1,因为setTimeout是异步执行的。setTimeout有两个参数,第一个参数是函数,第二参数是时间值。调用setTimeout时,把函数参数,放到事件队列中。等主程序运行完以后,再调用函数。就像我们平时给元素绑定事件的操作是一样的
btn.onclick = function() {
alert('只有在点击的时候才会执行,setTimeout也是如此,只是绑定事件,等主程序运行完毕后,再去调用');
};
setTimeout(fn, time)我们可以理解为在指定的time之后,再放入事件队列中,如果此时队列为空,那么就直接调用fn。如果前面还有其他的事件,那就等待。
接下来再看下这个程序:
setTimeout(function() {
console.log(i);
}, 0);
var i = 1;
此时输出的结果是1,不会报错,因为真正去执行console.log(i)时,var i = 1已经执行完毕了
所以我们平时进行dom操作时可以先绑定事件,然后再去写其他逻辑。
window.onload = function() {
fn();
}
var fn = function() {
alert('hello')
};
这么写,完全是可以的,因为异步。
(2)有了这些认知现在再回首原题
for (var i = 0; i < 3; i++) {
setTimeout(function() {console.log(i);
}, 0);
console.log(i);
}
它等价于把for循环拆分以后的如下代码var i = 0;
setTimeout(function() {
console.log(i);
}, 0);
console.log(i);
i++;
setTimeout(function() {
console.log(i);
}, 0);
console.log(i);
i++;
setTimeout(function() {
console.log(i);
}, 0);
console.log(i);
i++;
由于setTimeout是在注册事件,在加载过程中并没有执行,所以可以进一步等价于以下代码
var i = 0;
console.log(i);
i++;
console.log(i);
i++;
console.log(i);
i++;
setTimeout(function() {
console.log(i);
}, 0);
setTimeout(function() {
console.log(i);
}, 0);
setTimeout(function() {
console.log(i);
}, 0);
=>结果显然是0,1,2,3,3,3
(3)延伸到闭包
首先我们把原题封装成一个函数
var fn = function() {
for (var i = 0; i < 3; i++) {
setTimeout(function() {
console.log(i);
}, 0);
console.log(i);
}
};
fn();
这与我们平时经常写的事件是一样的
(*)
var fn = function() {
var divs = document.querySelectorAll('div');
for (var i = 0; i < 3; i++) {
divs[i].onclick = function() {
alert(i);
};
}
};
fn();
在本例中alert(i)中的i是fn作用域中的=>这是闭包。
我理解的闭包就是能够读取其他函数内部变量的函数。由于在Javascript语言中,只有函数内部的子函数才能读取局部变量,因此可
以把闭包简单理解成"定义在一个函数内部的函数"。所以,在本质上,闭包就是将函数内部和函数外部连接起来的一座桥梁。
function f1(){var n=999;
function f2(){
alert(n);
}
return f2;
}
var result=f1();
result(); // 999
在上面的代码中,函数f2就被包括在函数f1内部,这时f1内部的所有局部变量,对f2都是可见的。但是反过来就不行,f2内部的局部
变量,对f1就是不可见的。这就是Javascript语言特有的"链式作用域"结构,子对象会一级一级地向上寻找所有父对象的变量。所
以,父对象的所有变量,对子对象都是可见的,反之则不成立。既然f2可以读取f1中的局部变量,那么只要把f2作为返回值,我们就
可以在f1外部读取它的内部变量了
让原题输出0,1,2
for (var i = 0; i < 3; i++) {
setTimeout((function(i) {
return function() {
console.log(i);
};
})(i), 0);
}
还可改装成为
for (var i = 0; i < 3; i++) {
(function(j){
setTimeout(function( j ) {
return function() {
console.log(j);
};
}, 0);
})(i)
}
还可改装成为
var output = function ( i ) {
setTimeout( function() {
console.log( i );
} , 0 );
}
for ( var i = 0; i < 3 ; i++){
output( i ); // 此时传过去的i被赋值了
}
- 小白滴认知
- 认知
- 认知
- 认知
- 认知
- 认知
- 认知
- 认知
- 认知
- 认知,从认知开始
- dephi认知
- 认知不协调
- 多线程认知
- Socket 认知
- size_t认知
- 认知心理学
- 认知失调
- hadoop认知
- 中共成立以前的北京党组织成员
- Unity下资源的压缩测试
- Python线程、进程和协程详解
- Java中String类的一些用法
- RabbitMQ原理简单介绍
- 小白滴认知
- CentOS 7 yum nginx MySQL PHP 简易环境搭建
- 调色版小程序
- Hyperpolyglots: Paragon or Folly?
- 浅谈Android 中BlueTooth
- 网页中MP4视频格式要求
- Hadoop学习常见问题及答案总结手册-可下载
- 《ACM书中题目》 V
- Ubuntu下安装Percona xtrabackup