JavaScript 变量提升 | 执行上下文 | 作用域

Sally ·
更新时间:2024-09-20
· 908 次阅读

文章目录变量提升执行上下文全局执行上下文函数执行上下文执行上下文栈作用域例题举个栗子 执行上下文栈:举个栗子 变量提升+执行上下文栈:举个栗子 预处理顺序举个栗子 预处理举个栗子 顺序执行举个栗子 作用域举个栗子 作用域 变量提升

JavaScript 中,函数及变量的声明都将被提升到函数的最顶部。变量可以在使用后声明,也就是变量可以先使用再声明。

声明了a,没声明b,输出a不会报错,但是输出b会报错==>变量可以先使用再声明。
变量的提升只会把声明提升,但是初始化不会提升,也就是说可以输出a,但是a = 5却没有输出出来。
在这里插入图片描述

函数可以先使用后声明。
变量提升会把function声明的全局函数都提前。注意只有这种可以提升哦。别的方法声明的函数就不可以。
在这里插入图片描述
在这里插入图片描述
注意: 严格模式(strict mode)不允许使用未声明的变量。并且只有var声明的变量可以提升。

执行上下文

代码分类(位置)

全局代码 函数代码 全局执行上下文

在执行全局代码前将window确定为全局执行上下文,对全局数据进行预处理
(按照顺序来的嗷。预处理之后执行顺序也是按照这个顺序哦。不理解的看后边的例子)

var定义的全局变量==>undefined, 添加为window的属性 function声明的全局函数==>赋值(fun), 添加为window的方法 this==>赋值(window) 开始执行全局代码 函数执行上下文

在调用函数, 准备执行函数体之前, 创建对应的函数执行上下文对象,对局部数据进行预处理

形参变量==>赋值(实参)==>添加为执行上下文的属性 arguments==>赋值(实参列表), 添加为执行上下文的属性 var定义的局部变量==>undefined, 添加为执行上下文的属性 function声明的函数 ==>赋值(fun), 添加为执行上下文的方法 this==>赋值(调用函数的对象) 开始执行函数体代码 执行上下文栈

在全局代码执行前, JS引擎就会创建一个栈来存储管理所有的执行上下文对象

在全局执行上下文(window)确定后, 将其添加到栈中(压栈) 在函数执行上下文创建后, 将其添加到栈中(压栈) 在当前函数执行完后,将栈顶的对象移除(出栈) 当所有的代码执行完后, 栈中只剩下window 作用域

一个代码段所在的区域,它是静态的(相对于上下文对象), 在编写代码时就确定了,用来隔离变量,不同作用域下同名变量不会有冲突
分类

全局作用域 函数作用域 没有块作用域(ES6有了)

在这里插入图片描述
作用域和执行上下文的关系

区别1 全局作用域之外,每个函数都会创建自己的作用域,作用域在函数定义时就已经确定了。而不是在函数调用时 全局执行上下文环境是在全局作用域确定之后, js代码马上执行之前创建 函数执行上下文环境是在调用函数时, 函数体代码执行之前创建 区别2 作用域是静态的, 只要函数定义好了就一直存在, 且不会再变化 上下文环境是动态的, 调用函数时创建, 函数调用结束时上下文环境就会被释放 联系 上下文环境(对象)是从属于所在的作用域 全局上下文环境==>全局作用域 函数上下文环境==>对应的函数使用域

作用域链
多个上下级关系的作用域形成的链, 它的方向是从下向上的(从内到外),查找变量时就是沿着作用域链来查找的

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

我们可以在左下角看到一个栈。现在我们是执行了到了y=2这一步。

先将window压栈 执行sum(a),将sum压栈 sum里调用了mul,将mul压栈 执行完mul,y=2,num=5,输出10,执行完mul之后将mul出栈, 回到sum,执行num++(num++是先使用num执行,执行完后再+1),执行完sum将sum出现 现在栈里只剩window,执行完毕。
在这里插入图片描述 举个栗子 变量提升+执行上下文栈: console.log('global begin: ' + i) var i = 1 foo(1); function foo(i) { if (i == 4) { return; } console.log('foo() begin:' + i); foo(i + 1); console.log('foo() end:' + i); } console.log('global end: ' + i)

在这里插入图片描述

举个栗子 预处理顺序

输出function,因为预处理顺序是var变量,function函数,this指针

function a() {} var a; console.log(typeof a) 举个栗子 预处理 if (!(b in window)) { var b = 1; } console.log(b)

在这里插入图片描述
在这里插入图片描述

举个栗子 顺序执行

输出报错在这里插入图片描述
全局预处理顺序:var变量、function函数、this指针然后顺序执行代码

var c = 1 function c(c) { console.log(c) var c = 3 } c(2)

预处理之后先执行给a赋值,这时候a是number类型。然后执行c(2)自然会报错说c不是函数
在这里插入图片描述

举个栗子 作用域

作用域在定义的时候已经确定了!!!

var x = 10; function fn() { console.log(x); } function show(f) { var x = 20; f(); } show(fn);

在这里插入图片描述

举个栗子 作用域

在这里插入图片描述

我是萝莉安,你们看懂了没呀,这个应该很简单。


作者:LolitaSian



上下文 作用域 变量 JavaScript

需要 登录 后方可回复, 如果你还没有账号请 注册新账号