前言
从概念的字面意义上说,"变量提升”意味着变量和函数的声明会在物理层面移动到代码的最前面,但这么说并不准确。实际上变量和函数声明在代码里的位置是不会动的,而是在编译阶段被放入内存中。
不多说,直接撸代码吧 ~~~///(^v^)\\\~~~正文
什么是变量提升?
javascript在被解析的时候,会有一个预解析阶段,这个时候解析器会将当前上下文环境中的所有变量(不包括es6中的let和const声明)和函数声明提升到最前面。
先来看下面的代码:
'use strict'; console.log(a); // undefined var a = 1; console.log(a); // 1复制代码
那么在代码被解析的时候,就是这样:
'use strict'; var a; console.log(a); // undefined a = 1; console.log(a); // 1复制代码
那么这个过程就很好理解了。
但是如果有多个同名变量呢?同名变量声明
同一作用域下,对于同名变量声明,采用的是忽略原则,后声明的会被忽略,变量的赋值,会采取覆盖原则。
- 同一作用域下同名变量声明
看如下代码:
'use strict'; console.log(a); // undefined var a = 1; console.log(a); // 1 var a = 2; console.log(a); // 2复制代码
解析后的代码如下:
'use strict'; var a; console.log(a); //undefined a = 1; console.log(a); // 1 a = 2; console.log(a); // 2复制代码
- 不同作用域下同名变量声明
代码如下:
'use strict'; console.log(a); // undefined var a = 1; function b() { console.log(a); // undefined var a = 2; console.log(a); // 2 }; b();复制代码
解析后的代码如下(此处涉及到的执行上下文环境和作用域会另有文章详细说明):
1. 首先进入全局上下文环境,此时代码解析如下:
'use strict'; function b() { console.log(a); var a = 2; console.log(a); }; var a; console.log(a); // undefined a = 1; b();复制代码
2. 当执行到调用b函数的时候,进入b函数的上下文环境,b函数的代码被解析时,如下:
var a; console.log(a); // undefined a = 2; console.log(a); 2复制代码
在不同作用域中,就近原则,如果在当前作用域中找到,则不再向上一级作用域查找,如果没找到,则会找上一级作用域,一直找到全局作用域。
所以下面只讨论同一作用域下的情况。
同名函数声明
同一作用域下,对于同名函数声明,采用的是覆盖原则,先声明的会被覆盖。
代码如下:
'use strict'; console.log(a); // function a() { console.log(2) } function a() { console.log(1); }; function a() { console.log(2); }; console.log(a); // function a() { console.log(2) }复制代码
解析后的代码如下:
'use strict'; function a() { console.log(2); }; console.log(a); // function a() { console.log(2) } console.log(a); // function a() { console.log(2) }复制代码
同一作用域下,同名的函数声明和变量声明
对于同名的函数声明和变量声明,采用的是忽略原则,函数声明会提升到变量声明之前,变量声明会被忽略,函数声明有效。
代码如下:
'use strict'; console.log(a); // function a() {} var a; function a() {};复制代码
解析后的代码如下:
'use strict'; function a() {}; console.log(a); // function a() {}复制代码
如果存在赋值操作,就会采取覆盖原则。
看如下代码:'use strict'; console.log(a); // function a() {} var a = 1; function a() {}; console.log(a); // 1复制代码
解析后的代码如下:
'use strict'; function a() {}; console.log(a); // function a() {} a = 1; console.log(a); // 1复制代码
总结
- 同一作用域下,对于同名变量声明,采用的是忽略原则,后声明的会被忽略,变量的赋值,会采取覆盖原则。
- 同一作用域下,对于同名函数声明,采用的是覆盖原则,先声明的会被覆盖。
- 同一作用域下,对于同名的函数声明和变量声明,采用的是忽略原则,函数声明会提升到变量声明之前,变量声明会被忽略,函数声明有效。
如果有遗漏或者不对的地方,还请指正,先谢过~~~///(^v^)~~