JavaScript中的作用域

173 阅读1分钟

楔子

for(var i=0;i<10;i++){
    setTimeout(function(){console.log(i)},100*i)
}

输出

10
10
10
10
10
10
10
10
10
10

然而我们期望的输出是

0
1
2
3
4
5
6
7
8
9

修改一下上面的代码 IIFE

for(var i=0;i<10;i++){
    (function(i){
        setTimeout(function(){console.log(i)},100*i)
    })(i)
}

或者 使用 let 声明变量

for(let i=0;i<10;i++){
    setTimeout(function(){console.log(i)},100*i)
}

执行可以如我们所期望的一样输出结果
ES6之前的JavaScript没有块级作用域,{}中使用var定义的变量,在{}之外也可以访问。如

if(true){
    var i = 1;
}
console.log(i) // 1

使用let声明的变量,它使用的是块作用域

{
    let i = 0;
}
console.log(i)
Uncaught ReferenceError: i is not defined

定义在函数中的变量是函数作用域,函数的参数也是函数作用域

function foo(){
    var i = 1;
    console.log(i)
}
foo();
console.log(i)
Uncaught ReferenceError: i is not defined
var a = 2;
function koo(a){
    a = 1;
}
koo(a)
console.log(a)
2
var obj = {a:2};
function goo(a){
    a = 1;
}
goo(obj)
console.log(obj)
{a:2}

变量提升

var i = 1;
function foo(){
    console.log(i);
    var i = 2;
}
foo()

执行

undefined

相当于

var i = 1;
function foo(){
    var i;
    console.log(i);
    i = 2;
}

函数提升

函数表达式

foo();
function foo(){
    console.log(`foo`)
}

执行

foo

函数声明

foo(); 
var foo = function(){
    console.log(`foo`)
}

执行

Uncaught TypeError: foo is not a function

全局作用域

var i = 1;
function foo(){
    console.log(i)
}
foo()
1

全局变量的作用域是全局作用域,在任何地方都可以访问,应避免声明全局变量

作用域链

var a = 1;
function foo(){
    var b = 1;
    return function(){
        var c = 1;
        var r = a + b + c;
        return r;
    }
}
var koo = foo();
koo()
3