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