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