javascript --- > js中的作用域 && 变量提升

1 求以下函数的输出

1.1 考察点: 变量提升、this、作用域

// 考察点 作用域、this、变量提升
var a = 10
function test() {
  a = 100
  console.log(a)  
  console.log(this.a) 
  var a
  console.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=3var a = b
  • 在执行b=3时,JS解释器会自动在当前的全局环境下面挂在一个b属性,值为3
  • 所以会输出b=3a 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的时候要特别小心,它有一个变量提升…
  • 函数也存在变量提升,但是它比变量的提升慢

参考

源代码


发布了228 篇原创文章 · 获赞 41 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/piano9425/article/details/104216915