
获得徽章 0
- 闭包面试问题解答:
for (var i = 1; i < 6; i++) { setTimeout( function timer(){ console.log(i); },i*1000);}
输出5次6
原因:setTimeout的延迟不是绝对精确的;
setTimeout的意思是传递一个函数,延迟一段时候把该函数添加到队列当中,并不是立即执行;
所以说如果当前正在运行的代码没有运行完,即使延迟的时间已经过完,该函数会等待到函数队列中前面所有的函数运行完毕之后才会运行;也就是说所有传递给setTimeout的回调方法都会在整个环境下的所有代码运行完毕之后执行;
刚进入for循环的时候,i为1,所以相对于现在延迟一秒将timer函数添加到队列当中,然后for循环还要继续啊,并没有等一秒再继续循环啊,然后进行第二次循环,这时候i为2,所以相对于现在延迟两秒将timer函数送进队列。以此类推。for循环的时间忽略不计的话,timer函数就以每秒一次的频率执行啦。
为什么每次都显示6呢?
for(var i = 1; i <6; i++){...}中的i属于全局作用域,当settimeout函数执行时会向上级一层一层寻找,找到全局i,此时i为6.(再次提醒不要错误地认为要等timer函数执行之后才会继续循环);
解决办法一:for (var i = 1; i <6; i++) {
(function(i){
setTimeout( function timer() {
console.log(i);
}, 1000 );
})(i);
}
解决方法二:
for (let i = 1; i <6; i++) {
setTimeout( function timer() {
console.log(i);
}, j*1000 );
}
for(var i = 0 ; i < 6; i++){
setTimeout((function(i){
return function(){
console.log(i);
}
})(i),1000);
}
let原理:在ES6中let实际是为js新增了块级作用域,不用创造函数作用域就可以让每个函数访问各自作用域里的值,每次循环时候每个返回的函数引用的是其对应块作用域的变量
什么是闭包?
简言之, 闭包 是由函数引用其周边状态( 词法环境 )绑在一起形成的(封装)组合结构。在 JavaScript 中,闭包在 每个函数被创建时 形成。
闭包让我们能够从一个函数内部访问其外部函数的作用域 。要使用闭包,只需要简单地将一个函数定义在另一个函数内部内部函数将能够访问到外部函数作用域中的变量,即使外部函数已经执行完毕。
2.特性:
函数嵌套函数;
函数内部可以引用函数外部的参数和变量;
函数变量和参数不会被垃圾回收机制回收;
3.优缺点:
优点
- 希望一个变量长期驻扎在内存中
- 避免全局变量的污染
- 私有成员的存在
缺点
- 常驻内存,增大内存使用量,使用不当回造成内存泄漏;展开赞过评论1 - 有错误的地方希望各位指点一下
for (var i = 1; i < 6; i++) { setTimeout( function timer(){ console.log(i); },i*1000);}
输出5次6
原因:setTimeout的延迟不是绝对精确的;
setTimeout的意思是传递一个函数,延迟一段时候把该函数添加到队列当中,并不是立即执行;
所以说如果当前正在运行的代码没有运行完,即使延迟的时间已经过完,该函数会等待到函数队列中前面所有的函数运行完毕之后才会运行;也就是说所有传递给setTimeout的回调方法都会在整个环境下的所有代码运行完毕之后执行;
刚进入for循环的时候,i为1,所以相对于现在延迟一秒将timer函数添加到队列当中,然后for循环还要继续啊,并没有等一秒再继续循环啊,然后进行第二次循环,这时候i为2,所以相对于现在延迟两秒将timer函数送进队列。以此类推。for循环的时间忽略不计的话,timer函数就以每秒一次的频率执行啦。
为什么每次都显示6呢?
for(var i = 1; i <6; i++){...}中的i属于全局作用域,当settimeout函数执行时会向上级一层一层寻找,找到全局i,此时i为6.(再次提醒不要错误地认为要等timer函数执行之后才会继续循环);
解决办法一:for (var i = 1; i <6; i++) {
(function(i){
setTimeout( function timer() {
console.log(i);
}, 1000 );
})(i);
}
解决方法二:
for (let i = 1; i <6; i++) {
setTimeout( function timer() {
console.log(i);
}, j*1000 );
}
for(var i = 0 ; i < 6; i++){
setTimeout((function(i){
return function(){
console.log(i);
}
})(i),1000);
}
let原理:在ES6中let实际是为js新增了块级作用域,不用创造函数作用域就可以让每个函数访问各自作用域里的值,每次循环时候每个返回的函数引用的是其对应块作用域的变量
什么是闭包?
简言之, 闭包 是由函数引用其周边状态( 词法环境 )绑在一起形成的(封装)组合结构。在 JavaScript 中,闭包在 每个函数被创建时 形成。
闭包让我们能够从一个函数内部访问其外部函数的作用域 。要使用闭包,只需要简单地将一个函数定义在另一个函数内部内部函数将能够访问到外部函数作用域中的变量,即使外部函数已经执行完毕。
2.特性:
函数嵌套函数;
函数内部可以引用函数外部的参数和变量;
函数变量和参数不会被垃圾回收机制回收;
3.优缺点:
优点
- 希望一个变量长期驻扎在内存中
- 避免全局变量的污染
- 私有成员的存在
缺点
- 常驻内存,增大内存使用量,使用不当回造成内存泄漏;展开评论点赞 - 有错误的地方希望各位指点一下
for (var i = 1; i < 6; i++) { setTimeout( function timer(){ console.log(i); },i*1000);}
输出5次6
原因:setTimeout的延迟不是绝对精确的;
setTimeout的意思是传递一个函数,延迟一段时候把该函数添加到队列当中,并不是立即执行;
所以说如果当前正在运行的代码没有运行完,即使延迟的时间已经过完,该函数会等待到函数队列中前面所有的函数运行完毕之后才会运行;也就是说所有传递给setTimeout的回调方法都会在整个环境下的所有代码运行完毕之后执行;
刚进入for循环的时候,i为1,所以相对于现在延迟一秒将timer函数添加到队列当中,然后for循环还要继续啊,并没有等一秒再继续循环啊,然后进行第二次循环,这时候i为2,所以相对于现在延迟两秒将timer函数送进队列。以此类推。for循环的时间忽略不计的话,timer函数就以每秒一次的频率执行啦。
为什么每次都显示6呢?
for(var i = 1; i <= 5; i++){...}中的i属于全局作用域,当settimeout函数执行时会向上级一层一层寻找,找到全局i,此时i为6.(再次提醒不要错误地认为要等timer函数执行之后才会继续循环);
解决办法一:for (var i = 1; i <= 5; i++) {
(function(i){
setTimeout( function timer() {
console.log(i);
}, 1000 );
})(i);
}
解决方法二:
for (let i = 1; i <= 5; i++) {
setTimeout( function timer() {
console.log(i);
}, j*1000 );
}
for(var i = 0 ; i < 6; i++){
setTimeout((function(i){
return function(){
console.log(i);
}
})(i),1000);
}
let原理:在ES6中let实际是为js新增了块级作用域,不用创造函数作用域就可以让每个函数访问各自作用域里的值,每次循环时候每个返回的函数引用的是其对应块作用域的变量
什么是闭包?
简言之, 闭包 是由函数引用其周边状态( 词法环境 )绑在一起形成的(封装)组合结构。在 JavaScript 中,闭包在 每个函数被创建时 形成。
闭包让我们能够从一个函数内部访问其外部函数的作用域 。要使用闭包,只需要简单地将一个函数定义在另一个函数内部内部函数将能够访问到外部函数作用域中的变量,即使外部函数已经执行完毕。
2.特性:
函数嵌套函数;
函数内部可以引用函数外部的参数和变量;
函数变量和参数不会被垃圾回收机制回收;
3.优缺点:
优点
- 希望一个变量长期驻扎在内存中
- 避免全局变量的污染
- 私有成员的存在
缺点
- 常驻内存,增大内存使用量,使用不当回造成内存泄漏;展开评论点赞 - display: none;与visibility: hidden;的区别
联系:它们都能让元素不可见
区别:
display:none;会让元素完全从渲染树中消失,渲染的时候不占据任何空间;visibility: hidden;不会让元素从渲染树消失,渲染师元素继续占据空间,只是内容不可见display: none;是非继承属性,子孙节点消失由于元素从渲染树消失造成,通过修改子孙节点属性无法显示;visibility: hidden;是继承属性,子孙节点消失由于继承了hidden,通过设置visibility: visible;可以让子孙节点显式修改常规流中元素的display通常会造成文档重排。修改visibility属性只会造成本元素的重绘。读屏器不会读取display: none;元素内容;会读取visibility: hidden;元素内容展开等人赞过212