js函数高级:05、详解作用域与作用域链(作用域、作用域与执行上下文、作用域链)及相关面试题

javascript 的作用域、作用域与执行上下文、作用域链及相关面试题解:

Ⅰ、作用域:

其一、代码为:

html 复制代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>01_作用域</title>
</head>
<body>
	<!--  
	1、理解:
		* 就是一块"地盘",一个代码段所在的区域
		* 它是静态的(相对于上下文对象),在编写代码时就确定了

	2、分类:
		* 全局作用域
		* 函数作用域
		* 没有块作用域(ES6 有了)

	3、作用:
		* 隔离变量,不同作用域下同名变量不会有冲突

	4(*)、作用域个数的确定:定义函数的个数 + 全局作用域(即:N + 1)

	-->
	<script type="text/javascript">

	/* 
	// 没块作用域
	if(true) {
		var c = 3
	}
	console.log(c)
	*/
	
	var a = 10, 
			b=20
	function fn(x) {
		var a = 100,
				c = 300
		console.log('fn()', a, b, c, x)// 'fn()', 100, 20, 300, 10

		function bar(x) {
			var a = 1000,
			    d = 400
			console.log('bar()', a, b, c, d, x)// 第一次:'bar()', 1000, 20, 300, 400, 100
																				 // 第二次:'bar()', 1000, 20, 300, 400, 200
		}

		bar(100)
		bar(200)
	}

	fn(10)
		
	</script>
</body>
</html>

其二、结果为:

// 一进入页面后的控制台:

其三、作用域与作用域链_作用域代码图解:

Ⅱ、作用域与执行上下文:

其一、代码为:

html 复制代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>02_作用域与执行上下文</title>
</head>
<body>
	<!--  
	1、区别1:
		* 全局作用域之外,每个函数都会创建自己的作用域,作用域在函数定义时就已经确定了,而不是在函数调用时;
		* 全局执行上下文环境是在全局作用域确定之后,js 代码马上执行之前创建;
		* 函数执行上下文是在调用函数时,函数体代码执行之前创建;

	2、区别2:
		* 作用域是静态的,只要函数定义好了就一直存在,且不会再变化
		* 执行上下文是动态的,调用函数时创建,函数调用结束时就会自动释放

	3、联系:
		* 执行上下文(对象)是从属于所在的作用域
		* 全局上下文环境 ==> 全局作用域
		* 函数上下文环境 ==> 对应的函数使用域

	4(*)、小结:作用域在执行上下文之前创建,作用域是静态的(即:函数定义就创建)而上下文是动态的(即:函数调用才创建);

	-->
	<script type="text/javascript">

	var a = 10, 
			b=20
	function fn(x) {
		var a = 100,
				c = 300
		console.log('fn()', a, b, c, x)// 'fn()', 100, 20, 300, 10

		function bar(x) {
			var a = 1000,
			    d = 400
			console.log('bar()', a, b, c, d, x)// 第一次:'bar()', 1000, 20, 300, 400, 100
																				 // 第二次:'bar()', 1000, 20, 300, 400, 200
		}

		bar(100)
		bar(200)
	}

	fn(10)
		
	</script>
</body>
</html>

其二、结果为:

// 一进入页面后的控制台:

其三、作用域与作用域链_作用域与执行上下文代码图解:

Ⅲ、作用域链:

其一、代码为:

html 复制代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>03_作用域链</title>
</head>
<body>
	<!--  
	1、理解:
		* 多个上下级关系的作用域形成的链,它的方向是从下向上的(从内到外)
		* 查找变量时就是沿着作用域链来查找的

	2、查找一个变量的查找规则:
		* 在当前作用域下的执行上下文中查找对应的属性,如果有直接返回,否则进入 2;
		* 在上一级作用域的执行上下文中查找对应的属性,如果有直接返回,否则进入 3;
		* 再次执行 2 的相同操作,直到全局作用域,如果还找不到就抛出找不到的异常;

	-->
	<script type="text/javascript">

	var a = 1
	function fn1() {
		var b = 2
		function fn2() {
			var c = 3
			console.log(c)// 3
			console.log(b)// 2
			console.log(a)// 1
			console.log(d)// Uncaught ReferenceError: d is not defined(即:报错,d 未被定义)
		}
		fn2()
	}

	fn1()
		
	</script>
</body>
</html>

其二、结果为:

// 一进入页面后的控制台:

其三、作用域与作用域链_作用域链实例1代码图解:

Ⅳ、面试题:

其一、题1代码:

html 复制代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>04_作用域_面试题1</title>
</head>
<body>
	<script type="text/javascript">
	
	var x = 10
	function fn() {
		console.log(x)
	}
	function show(f) {
		var x = 20
		f()
	}

	show(fn)// 10
					// 原因:作用域与作用域之间的关系在函数定义时候就已经确认了,因此 fn 函数与 show 函数是平级的,
					// 因此执行 console.log(x) 代码时,会在本函数中查找 x 的值,没找到就去全局作用域下找,而非调用 fn 函数的 show 函数中找,因此输出是 10;
	</script>
</body>
</html>

其二、结果为:

// 一进入页面后的控制台:

其三、题2代码:

html 复制代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>05_作用域_面试题2</title>
</head>
<body>
	<script type="text/javascript">

	var fn = function() {
		console.log(fn)
	}
	fn()// ƒ () { console.log(fn) }
		  // 即:正常输出,输出 fn 整个函数;

			
	var obj = {
		fn2: function() {
			// console.log(fn2)
			console.log(obj.fn2)/* 
													ƒ () {
														// console.log(fn2)
														console.log(obj.fn2)
														console.log(this.fn2)
													}
													*/
			console.log(this.fn2)/* 
													ƒ () {
														// console.log(fn2)
														console.log(obj.fn2)
														console.log(this.fn2)
													}
													*/
		}
	}
	obj.fn2()// Uncaught ReferenceError: fn2 is not defined
					 // 报错原因:先在 fn2 函数作用域中并没有找到 fn2 函数,然后在全局作用域中查找 fn2 函数,发现也没有,因此报错 fn2 未被定义;
					 // 若想正常运行,可以输出 console.log(this.fn2) 或 console.log(obj.fn2) 即可,但使用 this.fn2 更方便;
		
	</script>
</body>
</html>

其四、结果为:

// 一进入页面后的控制台:

Ⅴ、小结:

其一、哪里有不对或不合适的地方,还请大佬们多多指点和交流!
其二、若有转发或引用本文章内容,请注明本博客地址(直接点击下面 url 跳转) https://blog.csdn.net/weixin_43405300,创作不易,且行且珍惜!
其三、有兴趣的话,可以多多关注这个专栏(Vue(Vue2+Vue3)面试必备专栏)(直接点击下面 url 跳转):https://blog.csdn.net/weixin_43405300/category_11525646.html?spm=1001.2014.3001.5482
其四、再有兴趣的话,也可以多多关注这个专栏(Java)(直接点击下面 url 跳转):https://blog.csdn.net/weixin_43405300/category_12654744.html?spm=1001.2014.3001.5482

相关推荐
少年姜太公19 小时前
什么?还不知道git cherry pick?
前端·javascript·git
白兰地空瓶21 小时前
🏒 前端 AI 应用实战:用 Vue3 + Coze,把宠物一键变成冰球运动员!
前端·vue.js·coze
Liu.7741 天前
vue3使用vue3-print-nb打印
前端·javascript·vue.js
松涛和鸣1 天前
Linux Makefile : From Basic Syntax to Multi-File Project Compilation
linux·运维·服务器·前端·windows·哈希算法
dly_blog1 天前
Vue 逻辑复用的多种方案对比!
前端·javascript·vue.js
做cv的小昊1 天前
【TJU】信息检索与分析课程笔记和练习(1)认识文献
经验分享·笔记·学习·搜索引擎·全文检索
万少1 天前
HarmonyOS6 接入分享,原来也是三分钟的事情
前端·harmonyos
烛阴1 天前
C# 正则表达式:量词与锚点——从“.*”到精确匹配
前端·正则表达式·c#
斌蔚司李1 天前
rayN 客户端使用说明
经验分享
wyzqhhhh1 天前
京东啊啊啊啊啊
开发语言·前端·javascript