js变量提升

428 阅读2分钟

首先把所有的声明提前,并且函数声明在变量声明之前,然后再赋值操作

注:提升是提升到其所在作用域的最顶端,不是提升到全局的最顶端
console.log(global); // undefined
var global = 'global';
console.log(global); // global
 
function fn () {
    console.log(a); // undefined
    var a = 'aaa';
    console.log(a); // aaa
}
fn();

为什么一开始打印global 会是undefined呢?

其实代码是按下面的顺序执行的

var global; // 变量提升,全局作用域范围内,此时只是声明,并没有赋值
console.log(global); // undefined
global = 'global'; // 此时才赋值
console.log(global); // 打印出global
 
function fn () {
    var a; // 变量提升,函数作用域范围内
    console.log(a);
    a = 'aaa';
    console.log(a);
}
fn();

如果函数声明和变量声明使用的是同一个变量名称,函数声明的优先级高于变量声明的优先级

例如

foo(); //输出1
var foo = function(){
  console.log(2)
}
function foo(){
  console.log(1)
}

它的执行顺序为:

function foo(){
  console.log(1)
}
var foo;
foo(); //输出1
foo = function(){console.log(2)}

自执行函数

var foo='hello'; 
(function(foo){
    console.log(foo);
    var foo=foo||'world';
    console.log(foo);
})();
console.log(foo);

执行如下:

var foo = 'hello';
(function () {
    var foo;
    console.log(foo);//undefined
    foo = foo || 'world';
    console.log(foo);//world
})();
console.log(foo);//hello

函数表达式的声明提升

函数提升优先级比变量提升优先级要高,且不会被变量声明覆盖,但是会被变量赋值覆盖

var getName = function (){
    console.log(2)
}
function getName(){
    console.log(1)
}
getName()

执行如下:

function getName(){
    console.log(1)
}
var getName;
getName = function (){
    console.log(2)
}
getName()  // 2

关于函数形参相关的提升,如果有形参传入,那么形参赋值是在变量提升之前

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

执行如下:

function fun(a){
    var a= 1; //形参传入并赋值
    var a; //内部变量提升
    console.log(a); //1
    a=2
}
fun(1)

还有一道老问题也是这个道理

var foo='hello'; 
(function(foo){
    console.log(foo);
    var foo=foo||'world';
    console.log(foo);
})(foo);
console.log(foo);

执行如下:

var foo='hello'; 
(function(foo){
    var foo = 'hello'; //形参传入并赋值
    var foo; //内部变量提升
    console.log(foo); //'hello'
    foo=foo||'world';
    console.log(foo); // 'hello'
})(foo);
console.log(foo); //'hello'