陕西队西北狼

JavaScript 之变量提升详解

#Js 变量提升#

一、解释:所谓JS “变量提升”,即变量可以在声明之前使用,值为undefined。

比如

a = 1;
var a;
console.log(a);

上述代码,如果按照自上而下的执行顺序的话,按理来说,应该输出 undefined,但是JavaScript 严格意义上并不是自上而下执行的语言。这段代码会输出1,因为存在变量提升,变量提升会将当前作用域声明的变量提升到程序顶部,因此,上述代码等价于=>

var a;
a = 1;
console.log(a);

 

二、赋值语句不会将变量声明提升

来看这个例子,

console.log(a);
var a = 1;

上述代码会报出 undefined,因为变量声明会提升,而赋值语句则不会将变量提升。对于JS 来说,其实 var a = 1; 是分两步的,1. var a; 2. a = 2; 而Js 只会将第一步提升到顶部,所以上述代码等价于=>

var a;
console.log(a);
a = 1;

 

三、为什么会有变量提升?

JS 和其他语言一样,都要经历编译和执行阶段,而JS 在编译阶段的时候,会搜集所有变量的声明并且提前声明变量,而其他语句则不会改变他们的顺序,因此,在编译阶段的时候,第一步就已经执行了,而第二步则是在执行阶段执行到该语句的时候才执行。

用 var 声明的变量才存在变量提升问题,而ES6 中使用 let 则不会有该问题。

 

函数声明和其他声明一起出现的时候,就可能引起一些困扰。

foo();

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

上述代码会输出 foo呢?还是报错呢? 

答案是输出 foo,因为函数声明和其他声明一起出现时,函数声明高于一切,函数是JS 的一等公民,这里,foo() 是先调用,后面才有它函数的声明,但是也可以使用该函数,原因就在于 JS 的函数其实是先声明,后使用,类似函数提升。

 

声明相同名称的函数,以最后一个为准:

foo();

function foo() {
    console.log('1');
}

function foo() {
    console.log('2');
}

上述代码,会打印出 2, 因为有多个同名函数声明的时候,后面的会覆盖前面的。

 

有了这么多案例,我们来看看下面这个问题:

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

上述代码会输出什么?会报错呢,还是输出 foo ? 答案是会报错,因为我们之前说过,变量的赋值没有变量提升的问题,所以上述代码类似于, 也就是说这里声明的是个foo变量,无法当函数用。

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

 

总结:

1.JS 使用 var 关键字声明的变量,会将变量提升到js 顶部执行,即变量提升,其实是因为JS 是先声明,后使用的,所有声明会在编译阶段先声明好。

2. 使用 var 关键字声明之后直接赋值,不存在变量提升。如 var a  = 1; 赋值语句不存在变量提升,对于函数先声明变量在直接赋值也一样,不存在变量提升。

3.声明同名函数,后面的会覆盖前面的,多个同名函数同时声明,只看最后一个。

 

posted @ 2020-02-24 14:54  PS-Jerry  阅读(1071)  评论(0编辑  收藏  举报