1 求以下函数的输出
1.1 考察点: 变量提升、this、作用域
// 考察点 作用域、this、变量提升
var a = 10
function test() {a = 100console.log(a) console.log(this.a) var aconsole.log(a)
}
test()
- 第一个和第三个肯定是100
- 在node环境下,没有window的概念,因此输出的是 undefined. (最后答案 100 undefined100)
- 在浏览器环境下,在没用找到this时,会顺着作用域链找到window,而 window.a =10,因此会输出 10. (最后答案 100 10 100)
[稍微改进]
var a = 10;
function test(){console.log(a);a = 100;console.log(this.a);var a;console.log(a)
}
test();
- 此时根据与解析,会有如下:
var a = 10;
function test() {// var a;console.log(a);a = 100;console.log(this.a);var a;console.log(a)
}
test();
- 浏览器环境下因此答案为:
undefined 10 100
1.2 考察点: 闭包的作用域
(function(){var a = b = 3;
})()
console.log(b); // 3
console.log(a); // a is not defined
- 说明: 在非严格模式下面,出现了
var a = b = 3
,实际上是b=3
和var a = b
- 在执行
b=3
时,JS解释器会自动在当前的全局环境下面挂在一个b属性,值为3 - 所以会输出
b=3
和a is not defined
1.3 考察点: 事件循环、单线程异步
for(var i=1 ; i<=3; i++){setTimeout(function(){console.log(i)}, 0)
}
- 答案:
4 4 4
- JS是单线程异步,当遇到异步函数的时候,会将异步函数添加到异步函数队列中.
- for是同步任务,因此,优先执行了3次循环,然后再执行3次输出.此时,由于i的值是4 ,故输出 3个4
[变形]:
for(let i = 1; i<=3; i++){setTimout(function(){console.log(i);}, 0);
}
- 答案:
1 2 3
- 前面和上面一样的,但执行到输出i的时候, 由于
let
创建的变量是块级作用域. - 可以看作是把i 同异步函数一起放在一个块中,放入异步函数的队列中.
- 当时间到了从异步队列中拿出块来执行
1.4 考察点: 作用域 变量提升 形参实参
function fun(n){console.log(n);var n = 456;console.log(n);
}
var n = 123;
fun(n);
- 根据与解析,函数实际如下
function fun(n){// var n = n;console.log(n);n = 456;console.log(n);
}
var n = 123;
fun(n);
- 答案为:
123 456
[稍微改进一下]
function fun(){console.log(n);var n = 456;console.log(n);
}
var n = 123;
fun(n);
- 答案是:
undefined 456
[再稍微改进一下]
function fun(){console.log(n);n = 456;console.log(n);
}
var n = 123;
fun(n);
- 此时没用变量提升,答案是
123 456
[再再稍微改进一下]
function fun(){console.log(fun);fun = 456;console.log(fun);
}
fun();
var fun = 123;
- 考察函数的提升和变量的提升,等价于,变量提升的速度快于函数提升
var fun = undefined;
var fun = function (){console.log(fun);fun = 456;console.log(fun);
}
fun();
fun = 123;
- 由于函数的提升比变量的提升慢,因此,在遇到
fun()
时,会先执行console.log(fun)
, - 此时会输出fun函数
- 然后fun赋值为456,然后的console.log会输出456
- 故输出结果为:
[Function fun] 456
[再再再稍微改进一下]
function fun(){console.log(fun);fun = 456;console.log(fun);
}
var fun = 123;
fun();
- 根据 变量提升,改造如下:
var fun = undefined;
var fun = function(){...};
fun = 123;
fun();
- 执行到
fun()
时,由于fun是一个变量,因此会报错:fun is not a function
[再再再再稍微改进一下]
var fun = 123;
function fun(){console.log(fun);fun = 456;console.log(fun);
}
fun();
- 变量提升改造如下:
var fun = undefined;
var fun = function(){...}
fun = 123
fun();
- 执行到
fun()
时,由于fun是一个变量,因此会报错:fun is not a function
2. 总结
- 使用var的时候要特别小心,它有一个变量提升…
- 函数也存在变量提升,但是它比变量的提升慢
参考
源代码