当前位置: 首页 > news >正文

前端技巧第十期JavaScript作用域链

作用域决定了变量函数对象的可访问范围,是JavaScript最基础的核心机制

一、作用域类型

全局作用域:脚本最外层声明的变量
const globalVar = '全局变量';
function test() {  
	console.log(globalVar); 
	// 可访问
}
函数作用域:通过var或函数声明创建
function funcScope() {  
	var funcVar = '函数内部变量';  
	console.log(funcVar); 
	// 正常输出
}
console.log(funcVar); // ReferenceError
块级作用域(ES6+):通过let/const创建
if (true) {  
	let blockVar = '块级变量';  
	const PI = 3.14;
}
if (true) {  let blockVar = '块级变量';  const PI = 3.14;}

二、作用域链:变量的寻址导航系统

访问变量时,JavaScript会沿着作用域链逐级向上查找
1. 链式结构形成原理
let global = 'G';
function outer() {
	let outerVar = 'O';
	function inner() {
		let innerVar = 'I';
		console.log(innerVar);    // I(当前作用域)
		console.log(outerVar);    // O(父级作用域)
		console.log(global);      // G(全局作用域)
	}
	inner();
}
outer();
inner作用域 → outer作用域 → 全局作用域 → null
2. 关键特性
静态词法作用域:链的链接关系在代码编写阶段确定
单向访问:内部作用域可访问外部,反之不行
遮蔽效应:同名变量会覆盖外层定义
let x = 10;
function shadowDemo() {
	let x = 20; // 遮蔽全局x
	console.log(x); // 20
}

三、执行上下文与作用域链的关系

每次函数调用都会创建新的执行上下文,其包含三个核心部分:
1:变量环境(Variable Environment)
2:词法环境(Lexical Environment)
3:this绑定
// 作用域链的物理实现:
ExecutionContext = {
	VariableEnvironment: { /* var变量 */ },
	LexicalEnvironment: {
		 outer: <父级词法环境引用>, // 构成作用域链的关键
		    /* let/const变量 */
	},
	ThisBinding: <this>
}

四、闭包:作用域链的经典应用

1: 闭包的本质是函数与其词法环境的引用捆绑。
function createCounter() {
	let count = 0;
	return {
	  increment: () => { count++; },
	  getValue: () => count
	};
}
const counter = createCounter();
const counter = createCounter();
console.log(counter.getValue()); // 1
2.:闭包的应用场景
模块化开发(私有变量封装)
防抖/节流函数
缓存计算结果
循环中正确处理异步回调

五、常见问题

1. 循环变量陷阱(经典面试题)
for (var i = 0; i < 3; i++) {  
	setTimeout(() => {    
		console.log(i); // 输出3次3  
	}, 100);
}
// 解决方案:使用IIFE或let
for (let i = 0; i < 3; i++) {  
	setTimeout(() => {    
	console.log(i); // 0,1,2  
	}, 100)
}
2. 变量提升的坑
console.log(a); // undefined(变量提升)
var a = 10;
console.log(b); // ReferenceError(暂时性死区)
let b = 20;
3. 严格模式的影响
'use strict';
function strictDemo() {  
	undeclaredVar = 10; // 抛出ReferenceError
}

七、思考

尽可能最小化全局变量:使用IIFE封装代码
优先使用const/let:避免变量提升问题
合理使用闭包:注意内存泄漏风险
模块化开发:使用ES6 Module管理作用域
命名空间模式:减少全局污染
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.dtcms.com/a/93823.html

相关文章:

  • 【银河麒麟系统常识】命令:dotnet --list-sdks(列出已安装的 .NET SDK 版本)
  • matlab打开两个工程
  • Redis 基础篇笔记
  • Android系统Launcher启动流程学习(三)Launcher启动流程
  • Windows 10 ARM64平台MFC串口程序开发
  • 前端知识点---事件委托和机制-阻止冒泡机制-阻止默认行为机制(javascript)
  • JavaScript描述Object.create()方法的原理及作用,如何利用它创建一个具有指定原型的对象?
  • java: 无法访问org.springframework.web.bind.annotation.GetMapping
  • 正则表达式-笔记
  • Transformer的理解
  • 7.2 分治-快排:LeetCode 912. 排序数组
  • Debezium日常分享系列之:Debezium 3.1.0.CR1发布
  • 01STM32时钟树
  • 【redis】哨兵节点作用演示和重选主节点详细流程
  • Vue $bus被多次触发
  • Android 删除aar中的一个类 aar包冲突 aar类冲突 删除aar中的一个包
  • 【JavaScript】筑基期功法
  • Spring Boot 自定义 Starter 组件的技术指南
  • Vue简单的store模式
  • 【解决方法】VMware安装Ubuntu时安装窗口过小看不到继续按钮 | Ubuntu安装窗口过小看不到按钮
  • kotlin多平台(KMP)开发桌面运行及打包
  • UDP数据报套接字编程
  • 三维动态规划-LeetCode3418. 机器人可以获得的最大金币数
  • 3.26学习总结 做题
  • WPS JS宏编程教程(从基础到进阶)--第二部分:WPS对象模型与核心操作
  • Tabby 一:如何在Mac配置保姆级教程(本地模型替换hugging face下载)
  • Linux: 文件系统
  • Python项目-基于Python的网络爬虫与数据可视化系统
  • 计算机 笔记
  • 蓝桥杯备考:动态规划之最长上升子序列打鼹鼠