JS 作用域和预解析

作用域

通常来说,一段程序代码中所用到的名字并不总是有效和可用的,而限定这个名字的可用性的代码范围就是这个名字的作用域。作用域的使用提高了程序逻辑的局部性,增强了程序的可靠性,减少了名字冲突。

作用域分为全局作用域和局部作用域。

es6的时候新增了块级作用域{ }。

全局变量和局部变量

根据作用域的不同,变量也可分为全局变量和局部变量。

全局变量:在全局作用域下声明的变量,在全局都可以使用。

  • 在全局作用域下var声明的变量是全局变量

  • 如果在函数内部没有声明直接赋值的变量也属于全局变量(不建议使用)
    局部变量:在局部作用域下声明的变量(在函数内部定义的变量)只能在函数内部使用。

  • 在函数内部var声明的变量就是局部变量

二者区别

全局变量:在任何一个地方都可以使用,只有在浏览器关闭时才会被销毁,因此比较占内存

局部变量:只在函数内部使用,当其所在的代码块被执行时,会被初始化;当代码块运行结束后,就会被销毁,因此更节省内存空间。

作用域链

内部函数访问外部函数的变量,采取的是链式查找的方式来决定取哪个值,这种结构我们称为作用域链(就近原则)

下面这个代码,就近原则输出的是20。

预解析

js引擎分为两步:预解析 代码执行

(1)预解析 js引擎会把 js中所有的 var 还有function 提升到当前作用域的最前面

(2)代码执行 按照代码书写的顺序从上往下执行

预解析分为变量预解析(变量提升)函数预解析(函数提升)

变量预解析

变量提升 就是把所有的变量声明提升 到当前的作用域最前面,不提升赋值操作。

javascript 复制代码
console.log(num)  
var num=10;

//相当于执行了以下代码

var num;   //预解析,把变量声明提升上来
console.log(num);
num=10;  //赋值不提升

上面这段代码预解析时会把变量声明提升到最前面,但不提升赋值操作,所以上面那个代码console.log(num)时num还没有被赋值,会输出undefined。

注意函数表达式,是用一个变量存储函数的,预解析时只提升变量声明不提升变量赋值。所以函数表达式调用必须要写在函数表达式的下面,不然会出错。

javascript 复制代码
// 函数表达式 调用必须要写在函数表达式的下面
fun();   //所以这里会输出undefined
var fun=function(){
	console.log(22);   
}

//相当于执行了以下代码
var fun; //提升了变量声明
fun();
fun=function(){  //变量赋值不提升
  console.log(22);
}

函数预解析

函数提升 就是会把函数声明提升 到当前作用域最前面,不提升调用操作。

javascript 复制代码
fn();
function fn(){
	console.log(22)
}

//预解析
//相当于执行下面的代码,所以不会报错
function fn(){   //函数声明
	console.log(22)
}
fn();   //函数调用

一道易错题:

javascript 复制代码
f1();
console.log(c);
console.log(b);
console.log(a);
function f1(){
  var a=b=c=9;
  console.log(a);
  console.log(b);
  console.log(c);
}

// 预解析
//相当于以下代码
function f1(){  //把函数声明提升
  var a;  //变量提升
  a=9;b=9;c=9;
  console.log(a);
  console.log(b);
  console.log(c);
}
f1();  //调用f1()输出9 9 9
console.log(c);
console.log(b);
console.log(a);

//外面输出的是 9 9 undefined 

这道题易错点是:

var a=b=c=9; 相当于var a=9;b=9;c=9;

而不是集体声明,集体声明应该为 var a=9,b=9,c=9;

因为在函数内部没有声明直接赋值的变量也属于全局变量,所以++b和c是全局变量++。a是在函数内部声明的,所以a是局部变量。

相关推荐
清汤饺子2 小时前
OpenClaw 本地部署教程 - 从 0 到 1 跑通你的第一只龙虾
前端·javascript·vibecoding
颜酱2 小时前
图的数据结构:从「多叉树」到存储与遍历
javascript·后端·算法
爱吃的小肥羊4 小时前
比 Claude Code 便宜一半!Codex 国内部署使用教程,三种方法任选一!
前端
IT_陈寒5 小时前
SpringBoot项目启动慢?5个技巧让你的应用秒级响应!
前端·人工智能·后端
树上有只程序猿6 小时前
2026低代码选型指南,主流低代码开发平台排名出炉
前端·后端
橙某人6 小时前
LogicFlow 小地图性能优化:从「实时克隆」到「占位缩略块」!🚀
前端·javascript·vue.js
高端章鱼哥6 小时前
为什么说用OpenClaw对打工人来说“不划算”
前端·后端
大脸怪6 小时前
告别 F12!前端开发者必备:一键管理 localStorage / Cookie / SessionStorage 神器
前端·后端·浏览器
Mr_Mao6 小时前
我受够了混乱的 API 代码,所以我写了个框架
前端·api
小徐_23336 小时前
向日葵 x AI:把远程控制封装成 MCP,让 AI 替我远程控制设备
前端·人工智能