Skip to content

JS变量/函数提升 #3

@zhang0ZGC

Description

@zhang0ZGC

这里讨论的是ES6之前的语法问题,自ES6以来,由于let、const声明的作用,作用域有所不同

JS代码在执行的时候,会先把变量申明提到最前面,也就是 js 会先把所有变量先申明好后再进行赋值等操作,并不是一边申明一边赋值。

变量提升

例1

var a=1;
var b=1;

实际是这样解析的:

var a;
var b;
a=1;
b=1;

例2

function foo() {
    var a=1;
    console.log(a);
    console.log(b);
    var b=1;
}
// print => 1
// print => undefined
foo();

实际:

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

image

例3

function foo() {
    console.log(a);
    a = 1;
    var a = 2;
    console.log(a);
}
// print => undefined
// print => 2;
foo();

这个有点复杂,有些人可能会认为,前面 a=1 会不会就是声明了一个全局变量 a, 后面再声明局部变量,可以写个代码验证一下:
image
image

可以看到,如果没有后面的 var a=2; 前面 a=1 就是声明一个全局变量了。

所以前面的例子实际是这样的:

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

image

函数提升

函数声明和变量相同,也会在块的顶部先申明

例1

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

// print => bar(){}
foo();

实际的样子:

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

变量声明和函数声明同时存在

变量声明和函数声明同时存在时,遵循变量声明优先于函数声明的原则

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

实际:

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

image

总结

总之,在相同作用域内,不管变量/函数写在什么位置,所有变量/函数都会被整体提升到作用域顶部,且函数申明是整体都在变量声明后面的。

当然了,如今这个都用 letconst 的时代,里面有些规则是不适用的,因为浏览器压根不允许里面的一些操作。

let/const 大法好远离 var 保平安 😄

Ref

https://es6.ruanyifeng.com/?search=%E5%8F%98%E9%87%8F%E6%8F%90%E5%8D%87&x=0&y=0#docs/let#%E5%9D%97%E7%BA%A7%E4%BD%9C%E7%94%A8%E5%9F%9F

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions