作用域链及变量提升

本文详细介绍了JavaScript的变量提升、运行机制等知识。变量提升阶段,带var的变量只声明,function变量声明且定义。代码执行前先开辟全局作用域并进行变量提升,执行中对var变量赋值。还阐述了私有和全局变量、函数重复声明、带var与不带var定义变量的区别,以及作用域和作用域链。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

变量提升
  1. 变量提升(预解释,预处理): 在执行js代码之前,浏览器会对所有带var或者function的变量进行提前的声明或者定义
    • 声明: 声明一个变量,告诉浏览器有这么个变量
    • 定义: 给变量赋值
  2. 区别:
    在变量提升阶段
    • 对带var的变量只提前声明不提前定义
    • 对带function的变量不仅提前声明而且提前定义
  3. 完成变量提升阶段之后,代码才从上至下执行
    • 在执行到 var 变量 = 值;才会对带var的变量进行赋值操作,也就是说经过这一行之变量才代表具体的值,在此之前是undefined
    • 在执行到function 函数名(){…}的时候,因为在变量提升阶段已经对这个函数进行过声明以及定义,浏览器会忽略这些函数定义的代码,不会重复定义
  4. 所以,在普通变量赋值之前使用就是undefined,赋值之后才是具体的值,而function声明的函数名在声明前使用是函数本身,在声明后使用还是函数本身.
变量提升小细节
  1. 变量提升只发生在等号的左侧,等号的右侧不会进行变量提升
  2. 条件语句中的变量无论是否成立都会进行变量提升.
  3. return下面的代码在执行阶段虽然不执行,但是在变量提升阶段会进行变量提升
  4. return 右边的代码会执行,但是在变量提升阶段不会进行提升
js代码的运行机制
  1. 在js代码执行之前,浏览器会开辟一个全局作用域,然后对全局中的变量进行变量提升操作(var/function)
  2. 变量提升结束后,js代码开始从上到下执行,执行过程中对var变量进行赋值
    • 如果赋值的是一个基本数据类型的值,那么直接把基本数据类型的值存在作用域中,并把变量和值关联起来
    • 如果赋值的是一个引用数据类型的值,浏览器会开辟一个堆内存,堆内存中储存这个引用数据类型的值,然后把堆内存的空间地址赋值给变量(这时候堆内存的地址是储存在作用域中的)
  3. 如果执行过程中遇到函数,执行会经历以下几步
    • 开辟一个新的堆内存(一个新的作用域,互相不打扰,这也解释了为什么函数每次执行都相互独立)
    • 形参赋值
    • 变量提升
    • 执行代码
    • 销毁作用域(如果作用域没有被占用)
私有变量和全局变量
  1. 全局变量: 在全局作用域中声明的变量
  2. 私有变量: 在私有作用域中声明的(函数作用域)
  3. 函数的形参也是私有变量
函数重复声明
  1. 同名变量只会声明一次,代表的值就是最后一次的值

var num =1;
var num =2; 
var num = 100; // num虽然var了3次,但是并不会声明3次,只会声明一次,同时只有最后一次才会将num的值赋值成100;

function fn() {
  console.log(1)
}
function fn() {
  console.log(2)
}
function fn() {
  console.log(3)
}
fn(); // 3
  1. 当函数名和变量名重名时,函数的优先级比变量的优先级高
    • 因为在变量提升阶段,变量重名时只会声明一次,但是因为函数的赋值优先级比变量优先级高,会先将函数的值赋值,直到执行完函数之后将函数的值改变为123.所以下面代码中,第一行输出fe这个函数,最后一行输出123.
console.log(fe); // 输出整个fe函数
function fe() { // 当代码执行到这里时,直接忽略,因为函数已经在变量提升阶段定义并赋值了
  console.log('789');
}
var fe = 123; // 代码执行到这一行时,将变量fe的值修改为123
console.log(fe) // 输出123
定义变量时带var跟不带var的区别
  1. 在全局作用域中,如果定义变量时带了var或者function,相当于在全局增加了一个同名属性(或者说键值对)
  2. 如果不带var,那么他就不是一个变量,且不会进行变量提升,在赋值之前使用会报错, 注意:不带var定义时,他也会在window中增加一个同名键值对
js的运行环境(栈内存):作用域
  1. 作用域(scope)的作用
    • 给js提供运行的环境
    • 存储基本数据类型
  2. 作用域的分类
    1. 全局作用域:浏览器打开页面的时候,首先会形成一个全局作用域,用来执行全局中的代码,全局作用域就是window对象(他是全局对象的一个实现,在js中是window,Node.js中是Global)
    2. 私有作用域(函数作用域): 函数执行时浏览器开辟的,只要函数执行就会形成一个新的私有作用域
    3. 块级作用域:把代码块(if,for循环的代码块…)变成作用域. 功能和私有作用域相似,是es6新增的
作用域链
  1. 作用域链就是变量的查找机制,当我们引用一个变量时,浏览器会首先在当前作用域中查找,看当前作用域中是否有这样一个变量,如果有就直接引用,如果没有就继续向上一级作用域查找,直到找到window, 在window中会先查看有没有需要查找的变量,没有的话会查找在window中有没有需要查找的属性,如果还没有就会报错
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值