JS 中的变量提升

JS 中的变量提升

参考不同的文章, 整理成为自己可理解的内容
文章原地址
出现的代码运行线上地址 javascript-visualizer
首先来看小例子

console.log('name: ', name) // undefined
console.log('age : ', age ) // undefined
console.log('sayHi ;', sayHi) // f sayHi()

var name = '小火车'
var age = 24
function sayHi () {
	return "sayHI"
}

打印出来的结果都是undefined
先了解JS的运行机制: 首先是创建阶段, 其次是执行阶段

在创建阶段的时候,JS引擎就会创建全局的window和this对象, 将所有的变量声明都赋予一个默认值undefined,所有的函数声明都被存入到内存中, 在执行阶段的时候,JS引擎就会将真实的值赋值给声明的变量

  • 在创建阶段的时候, JS引擎主要做的事情

    1.创建了全局的window对象
    2.创建了this对象
    3.给变量和函数分配内存
    4.给变量赋默认值undefined,把函数声明放进内存中

    在这里插入图片描述

  • 在执行阶段, JS引擎就会一步一步的执行代码, 将内存中的变量赋予真实值
    在这里插入图片描述

再回头看先前的代码

console.log('name: ', name) // undefined
console.log('age : ', age ) // undefined
console.log('sayHi ;', sayHi) // f sayHi()

var name = '小火车'
var age = 24
function sayHi () {
	return "sayHI"
}

JS的引擎开始执行console.log()代码的时候,这个时候已经就处于执行阶段了, 之前的创建阶段已经执行完毕, 变量的声明已经被赋予了默认值undefined, 同时函数的声明已经在内存中定义了, 因此nameage都是被赋予了undefined,sayHi也正是内存中函数的引用

何为变量提升: 在JS引擎创建阶段给变量赋予默认值undefined的过程就是变量提升
何为变量提升: 在JS引擎创建阶段给变量赋予默认值undefined的过程就是变量提升
何为变量提升: 在JS引擎创建阶段给变量赋予默认值undefined的过程就是变量提升

函数执行上下文
  • 函数执行上下文是在函数被调用的时候就被创建出来了

  • 在函数执行上下文的时候JS引擎创建的不是window对象, 而是arguments对象

    1.创建一个arguments对象
    2.创建this对象
    3.给变量和函数赋值
    4.给变量赋予默认值undefined, 把函数声明放进内存

  • 执行函数

    var name = "小火车"
    var age = 24
    
    function sayHi() {
        console.log("小火车")
    }
    sayHi()
    

    在这里插入图片描述

  • 可以看到在执行到sayHi()函数调用的时候, JS引擎在创建函数上下文的创建阶段的时候创建了arguments对象和this对象, 因为函数中没有任何的变量, JS引擎就不需要进行变量的提升和函数内存的分配

  • sayHi()函数执行完之后, 函数的执行过程就消失了, 因为JS引擎在函数调用的时候就会创建一个执行栈(也叫调用栈),每当函数被调用, 就会创建一个新的执行上下文, 并且加入到执行栈中(调用栈),当函数执行完毕之后就会从执行栈中弹出
    在这里插入图片描述

  • JS的单线程在执行函数嵌套函数的代码时,每一个新的函数调用(函数执行上下文),都会被嵌套到最初的函数执行上下文中,形成了一个调用栈
    在这里插入图片描述

作用域

小例子

function a() {
    var name = "小火车"
}
a()
console.log(name)
  • JS引擎的创建阶段可以看到name这个变量是没有声明的
    在这里插入图片描述
  • JS引擎执行到了a()函数的时候, 函数内部就会出现函数的执行上下文,在创建阶段创建了arguments对象和this对象, name变量就发生了变量提升现象,赋予默认值undefined
  • 之后到了执行阶段, name变量就会被赋予真实的数据
  • 最后函数执行完毕, a()函数的执行上下文结束, 在调用栈中被弹出
  • 再执行console.log(name)的时候,报错ReferenceError: name is not defined
    在这里插入图片描述
  • 通常情况下,函数内部定义的变量在函数外部访问不到, 传入函数的所有参数都被定义为局部变量存在于函数的执行上下文中, 简单来说作用域就是变量的可访问之处

小例子2

var name = "小火车"
function a() {
    console.log(name)
}
a()

打印出来的结果仍旧是小火车

  • 当执行函数中的执行上下文找不到相应的局部变量的时候, JS引擎就会到最接近的上级执行上下文查找, 这条查找链会一直延伸到全局上下文中, 如果仍旧找不到JS引擎就会抛出一个引用错误, 这个过程就是作用域链
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值