AI智能
改变未来

js中变量提升和函数提升


变量提升和函数提升的总结

  我们在学习JavaScript时,会遇到变量提升和函数提升的问题,为了理清这个问题,现做总结如下,希望对初学者能有所帮助

  我们都知道 var 声明的变量有变量提升,而 let 声明的变量和 const 声明的常量没有变量提升,但是为什么 let 声明的变量就不会变量提升呢?

首先我们得理解变量和函数的创建过程:

  变量声明 ==>变量初始化 ==>变量赋值

  函数声明 ==> 初始化 ==> 赋值

而变量提升和函数提升要完成的工作为:

  变量声明 ==> 变量初识化(undefined)

  函数声明 ==> 初始化 ==> 赋值(仅仅是赋值,并没有运行函数体)

暂时性死区的概念:

  ES6规定,如果代码区块中存在 let 和 const 命令声明的变量,这个区块对这些变量从一开始就形成了封闭作用域,直到声明语句完成,这些变量才能被访问(获取或设置),否则就会报错 ReferenceError。这在语法上称为“暂时性死区”,即代码块开始到变量声明语句完成之间的区域。通过 var 声明的变量拥有变量提升,没有暂时性死区。

  因为有暂时性死区的存在,所以 let 声明的变量和 const 声明的常量才 不能 变量提升

  

  从变量创建过程来理解:

  let 声明被提升了,但是并没有做初始化工作

  const 声明被提升,也是没有做初始化工作(const只有声明和初始化过程,没有赋值过程)

    let 和 const 都没有提升所要满足的工作,所以就无法提升

  var 的声明被提升,初始化被提升

  function 的声明、初始化、和赋值都被提升

var 声明的变量提升(声明、初始化都被提升,但是赋值没有提升)

  实例  

  console.log(a)  // undefined

  var a = \’hello world\’

  console.log(a)  // \’hello world\’

  实际执行过程如下

  var a

  console.log(a)  // undefined

  a = \’hello world\’

  console.log(a)  // \’hello world\’

function 声明的函数提升(声明、初始化、赋值都提升了)

  实例  

  fn()  // \’hello world\’

  function fn() { console.log(\’hello world\’) }

  fn()  // \’hello world\’

  实际执行过程如下

  function fn() { console.log(\’hello world\’) }  // 注意:此时函数体并没有运行

  fn()  // \’hello world\’

  fn()  // \’hello world\’

既有 var 声明的变量提升,又有 function 声明的函数提升

  实例

  变量名和函数名不同名  

  console.log(a)  // undefined

  fn()

  var a = 100

  console.log(a)  // 100

  function fn() {

    console.log(a)  // undefined

    var a = 10

    console.log(a)  // 10

   }

  var a = 200

  console.log(a)  // 200

  实际执行过程如下 

  function fn() {

    console.log(a)  

    var a = 10

    console.log(a)   

  }

  var a (全局变量)

  var a (局部变量)

  console.log(a)  // undefined

  fn()  // undefined  10

  a = 100

  console.log(a)  // 100

  a = 200

  con565sole.log(a)  // 200

  变量名和函数名同名 

  情况一:变量由 函数类型 变为 基本数据类型(如 Number)

  var a = 100

  console.log(a)  // 100

  a()  // 报错(TypeError:a is not a function)

  function a() {

    console.log(\’hello world\’) 

   }

  实际执行过程如下

  function a() {

    console.log(\’hello world\’) 

   }

  var a  // 用 var 重新声明了变量 a,但此时变量 a 指向的还是函数体本身,值未改变

  a = 100  //  重新给 a 赋值为 100,a 的值发生了改变,由函数类型变为了number类型

  console.log(a)  // 100

  a()  // 报错:此时 a 已经不是函数 a 了

 

  情况二:变量重新赋值,但未立即改变变量的值

  console.log(a)  // a(){ console.log(\’hello world\’)}  即 a 函数本身

  a()  // \’hello world\’

  var a = 100

  var a = 200

  var a = 300

  console.log(a)  // 300

  function a() {

    console.log(\’hello world\’) 

   }

  实际执行过程如下

  function a() {

    console.log(\’hello world\’)

   }

  var a  //  此时虽然重新声明了 a 变量,但是并没有改变 a 的值,此时的 a 还是个函数

  console.log(a)  // a(){ console.log(\’hello world\’)}  即 a 函数本身

  a = 100  // 重新给 a 变量赋值 100

  a = 200  // 重新给 a 变量赋值 200

  a = 300  // 重新给 a 变量赋值 300

  console.log(a)  // 100(此时变量 a 已经由 函数类型变为 基本数据类型number,且值为 100)

  a()  // 报错:此时 a 已经不是函数 a 了

用 let 定义的变量和用 const 定义的常量 没有提升

用 let 定义的变量

  在变量定义之前使用改变量 会报错

  console.log(a)  // 报错  Cannot access \’a\’ before initialization

  let a = 10

  

  在变量定义之后使用改变量 才能正常运行

  let a = 10  

  console.log(a)  // 10

总结:

  1. 用 var 定义的变量有变量提升,用 function 定义的函数有函数提升

  2. 函数提升优先级高于变量提升,即优先执行函数提升

  3. let 定义的变量和 const 定义的常量不会提升

  4. 重复用 var 定义的同一个变量是合法的,如果重复的声明有初始值,那就赋值;如果没有初始值,那么它不会对变量原来保存的值不会产生影响

  5. 不能用 let 重复定义同一个变量,会造成错误

赞(0) 打赏
未经允许不得转载:爱站程序员基地 » js中变量提升和函数提升