学习变量提升

106 阅读2分钟

此文是我在学习变量提升时的所思所想,整理起来以便和大家交流,如有不对之处,希望大家不吝赐教。 我在学些之前先找了几道题做了做

1.首先我们先来个简单的

console.log(foo) ////打印出undefined
var foo = 10

这道题大家都很熟悉吧,我们顺便复习一下变量提升的概念

什么是变量提升呢?

当栈内存(作用域)形成的,js代码自上而下执行之前,浏览器首先会把带有'var''function'关键字的进行提前'声明''定义',这种处理机制就叫做变量提升

我们会注意到ES6新增的let,const,他们也存在变量提升吗?

console.log(foo) //意料之中,报错了
let foo = 10

这里我们借用红宝书的一段话来解释这个现象:

严格来讲,let在js运行时也会进行变量提升,但由于暂时性死区的缘故,实际上不能在声明之前使用let变量。因此,从写javascript代码的角度来说,let的提升和var是不一样的

2.进阶 -- 函数声明提升

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

这段代码说明函数声明中,整个函数体也都会被提升。但是声明一个函数一般来说有两种方式,分别是: function 命令、函数表达式,那么他们在函数声明时有什么不同吗? 只有function 命令声明的方式会连函数体一起提升,而函数表达式中只会提升名称,函数体只有在执行到赋值语句时才会被赋值,为了证明这一现象,我们可以看看下面的例子

foo(); // TypeError "foo is not a function"
var foo = function () { // 函数表达式被赋值给变量'foo'
    alert("this won't run!");
}    

3.混合高阶 -- 由于在提升时函数声明会提升到变量声明之前,变量声明一定会被忽略,所以结果是函数声明有效

function foo(){
  console.log(1)
}
var foo; //被忽略
foo(); //1

fn(); //=>5
function fn(){ console.log(1); }  //=>提前声明加定义
fn(); //=>5
function fn(){ console.log(2); }  //=>此处覆盖前面的值
fn(); //=>5
var fn = function(){ console.log(3); }  //=>var fn不用再处理了,但是赋值在变量提升阶段没处理过,此处需要赋值  fn=window.fn=>3
fn(); //=>3
function fn(){ console.log(4); } 
fn(); //=>3
function fn(){ console.log(5); } 
fn(); //=>3