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

相关推荐
渣波1 小时前
# TypeScript:给 JavaScript 穿上“防弹衣”的超能力语言
javascript·typescript
我叫张小白。1 小时前
Vue3 标签的 ref 属性:直接访问 DOM 和组件实例
前端·javascript·vue.js·typescript·vue3
有点笨的蛋1 小时前
JavaScript 中的面向对象编程:从基础到继承
前端·javascript
2509_940880221 小时前
Spring Cloud GateWay搭建
android·前端·后端
一千柯橘1 小时前
Three.js 中的调试助手 OrbitControls + GUI
前端
一 乐1 小时前
购物商城|基于SprinBoot+vue的购物商城系统(源码+数据库+文档)
前端·javascript·数据库·vue.js·spring boot·后端
izx8881 小时前
ES6+ 核心语法精讲:让 JavaScript 更优雅、更强大
javascript
玥浛1 小时前
ELK.js 实战:大规模图布局性能优化方案
前端
特级业务专家1 小时前
React Fiber 和时间切片
前端