Webcourse/15-面试题积累/04-变量提升的题目.md

361 lines
4.5 KiB
Markdown
Raw Normal View History

2018-03-21 21:45:10 +08:00
## 变量提升
先说三句总结性的话:
- let 的「创建」过程被提升了,但是初始化没有提升。
- var 的「创建」和「初始化」都被提升了。
- function 的「创建」「初始化」和「赋值」都被提升了。
### 变量提升的规律
在进入一个执行上下文后,先把 var 和 function 声明的变量前置,再去顺序执行代码。
PS作用域分为全局作用域和函数作用域用var声明的变量只在自己所在的所用域有效。
我们举例来看看下面的代码。
**代码 1**
```javascript
console.log(fn);
var fn = 1;
function fn() {
}
console.log(fn);
```
相当于:
```javascript
var fn = undefined;
function fn() {
}
console.log(fn);
fn = 1;
console.log(fn);
```
打印结果:
![](http://img.smyhvae.com/20180321_1810.png)
**代码 2**
```javascript
console.log(i);
for (var i = 0; i < 3; i++) {
console.log(i)
}
```
相当于:
```javascript
var i = undefined;
console.log(i);
for (i = 0; i < 3; i++) {
console.log(i);
}
```
打印结果:
![](http://img.smyhvae.com/20180321_1817.png)
**代码 3**
```javascript
var a = 1;
function fn() {
a = 2;
console.log(a)
var a = 3;
console.log(a)
}
fn();
console.log(a);
```
相当于:
```javascript
var a = undefined;
function fn() {
var a
a = 2
console.log(a)
a = 3
console.log(a)
};
a = 1;
fn();
console.log(a);
```
打印结果:
![](http://img.smyhvae.com/20180321_1827.png)
参考链接:<https://github.com/jirengu/javascript-tutorial>
### 声明时的重名问题
假设`a`被声明为变量,紧接着`a`又被声明为函数,原则是:声明会被覆盖(先来后到,就近原则)。
PS
- 如果`a`已经有值,再用 var 声明是无效的。
- 如果`a`已经有值,紧接着又被赋值,则**赋值会被覆盖**。
举例1
```javascript
var fn; //fn被声明为变量
function fn() {// fn被声明为function就近原则
}
console.log(fn); //打印结果function fn(){}
```
举例2
```javascript
function fn() {} //fn被声明为function且此时fn已经被赋值这个值就是function的对象
var fn; //fn已经在上一行被声明且已经有值 再 var 无效,并不会重置为 undefined
console.log(fn) //打印结果function fn(){}
```
既然再var无效但是再function是有效的
```javascript
function fn() {} //fn被声明为function且此时fn已经有值这个值就是function的对象
function fn() { //此时fn被重复赋值会覆盖上一行的值
console.log('smyhvae');
}
console.log(fn)
```
打印结果:
![](http://img.smyhvae.com/20180321_1845.png)
### 函数作用域中的变量提升(两点提醒)
**提醒1**
在函数作用域也有声明提前的特性:
- 使用var关键字声明的变量是在函数作用域内有效而且会在函数中所有的代码执行之前被声明
- 函数声明也会在函数中所有的代码执行之前执行
因此在函数中没有var声明的变量都会成为**全局变量**,而且并不会提前声明。
举例1
```javascript
var a = 1;
function foo() {
console.log(a);
a = 2; // 此处的a相当于window.a
}
foo();
console.log(a); //打印结果是2
```
上方代码中foo()的打印结果是`1`。如果去掉第一行代码,打印结果是`Uncaught ReferenceError: a is not defined`
**提醒2**定义形参就相当于在函数作用域中声明了变量。
```
function fun6(e) {
console.log(e);
}
fun6(); //打印结果为 undefined
fun6(123);//打印结果为123
```
### 其他题目
**20180321面试题**
```javascript
var a = 1;
if (a > 0) {
console.log(a);
var a = 2;
}
console.log(a);
```
打印结果:
```
1
2
```
上方代码中不存在块级作用域的概念。if语句中用var定义的变量让然是全局变量。
顺便延伸一下用let定义的变量是在块级作用域内有效。
```javascript
```
```javascript
```
```javascript
```
```javascript
```
```javascript
```