JS中的函数提升、变量提升和Class提升是怎样的
Admin 2022-09-03 群英技术资讯 449 次浏览
sayHi() // Hi there!
function sayHi() {
console.log('Hi there!')
}
name = 'John Doe'
console.log(name) // John Doe
var name
然而JavaScript并不会移动你的代码,所以JavaScript中“变量提升”并不是真正意义上的“提升”。
JavaScript是单线程语言,所以执行肯定是按顺序执行。但是并不是逐行的分析和执行,而是一段一段地分析执行,会先进行编译阶段然后才是执行阶段。
在编译阶段阶段,代码真正执行前的几毫秒,会检测到所有的变量和函数声明,所有这些函数和变量声明都被添加到名为Lexical Environmen
t的JavaScript数据结构内的内存中。所以这些变量和函数能在它们真正被声明之前使用。
sayHi() // Hi there!
function sayHi() {
console.log('Hi there!')
}
因为函数声明在编译阶段会被添加到词法环境(Lexical Environment)中,当JavaScript引擎遇到sayHi()
函数时,它会从词法环境中找到这个函数并执行它。
lexicalEnvironment = {
sayHi: < func >
}
console.log(name) // 'undefined'
var name = 'John Doe'
console.log(name) // John Doe
上面的代码实际上分为两个部分:
var name
表示声明变量name
= 'John Doe'
表示的是为变量name
赋值为'John Doe'。var name // 声明变量
name = 'John Doe' // 赋值操作
只有声明操作var name
会被提升,而赋值这个操作并不会被提升,但是为什么变量name
的值会是undefined
呢?
原因是当JavaScript在编译阶段会找到var
关键字声明的变量会添加到词法环境中,并初始化一个值undefined
,在之后执行代码到赋值语句时,会把值赋值到这个变量。
// 编译阶段
lexicalEnvironment = {
name: undefined
}
// 执行阶段
lexicalEnvironment = {
name: 'John Doe'
}
所以函数表达式也不会被“提升”。helloWorld
是一个默认值是undefined
的变量,而不是一个function
。
helloWorld(); // TypeError: helloWorld is not a function
var helloWorld = function(){
console.log('Hello World!');
}
console.log(a) // ReferenceError: a is not defined
let a = 3
为什么会报一个ReferenceError
错误,难道let
和const
声明的变量没有被“提升”吗?
事实上所有的声明(function, var, let, const, class)都会被“提升”。但是只有使用var
关键字声明的变量才会被初始化undefined
值,而let
和const
声明的变量则不会被初始化值。
只有在执行阶段JavaScript引擎在遇到他们的词法绑定(赋值)时,他们才会被初始化。这意味着在JavaScript引擎在声明变量之前,无法访问该变量。这就是我们所说的Temporal Dead Zone,即变量创建和初始化之间的时间跨度,它们无法访问。
如果JavaScript引擎在let
和const
变量被声明的地方还找不到值的话,就会被赋值为undefined
或者返回一个错误(const
的情况下)。
举例:
let a
console.log(a) // undefined
a = 5
在编译阶段,JavaScript引擎遇到变量a
并将它存到词法环境中,但因为使用let
关键字声明的,JavaScript引擎并不会为它初始化值,所以在编译阶段,此刻的词法环境像这样:
lexicalEnvironment = {
a: <uninitialized>
}
如果我们要在变量声明之前使用变量,JavaScript引擎会从词法环境中获取变量的值,但是变量此时还是uninitialized
状态,所以会返回一个错误ReferenceError
。
在执行阶段,当JavaScript引擎执行到变量被声明的时候,如果声明了变量并赋值,会更新词法环境中的值,如果只是声明了变量没有被赋值,那么JavaScript引擎会给变量赋值为undefined
。
tips: 我们可以在let
和const
声明之前使用他们,只要代码不是在变量声明之前执行:
function foo() {
console.log(name)
}
let name = 'John Doe'
foo() // 'John Doe'
同let
和const
一样,class
在JavaScript中也是会被“提升”的,在被真正赋值之前都不会被初始化值, 同样受Temporal Dead Zone的影响。
let peter = new Person('Peter', 25) // ReferenceError: Person is not defined
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
}
let John = new Person('John', 25);
console.log(John) // Person { name: 'John', age: 25 }
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:mmqy2019@163.com进行举报,并提供相关证据,查实之后,将立刻删除涉嫌侵权内容。
猜你喜欢
JS中replace函数大小写有分吗?replace()函数表示将用一个字符串替换字符串中的所出现的特定内容。对于replace()方法区不区分大小写问题,有一些新手不是很清楚。对此,本文就给大家来详细的介绍一下replace()的使用。
目录打包部署后默认路由不正确问题描述解决方案vue打包后路径不对对于背景图片不显示的问题动画无法运行小图标没了打包部署后默认路由不正确问题描述vue项目本地开发的时候默认路由没问题,例如redirect:/index但是部署以后,服务器上默认路由不正确,现在遇到的问题是,会默认跳转到login页面,前提项目没有做路由权
这篇文章主要为大家介绍了Vue的监听属性,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助
在react中的三大属性有state、props、refs,这篇文章给大家分享的是有关react的state属性的内容,小编觉得挺实用的,因此分享给大家做个参考,接下来一起跟随小编看看吧。
今天给大家分享的是关于ECMAScript中的操作符的内容,在ECMAScript中操作符有很多,例如一元操作符、布尔操作符、乘性操作符、加性操作符、关系操作符等等,接下来小编就给大家来分别介绍一下这些操作符的用途及用法。
成为群英会员,开启智能安全云计算之旅
立即注册Copyright © QY Network Company Ltd. All Rights Reserved. 2003-2020 群英 版权所有
增值电信经营许可证 : B1.B2-20140078 粤ICP备09006778号 域名注册商资质 粤 D3.1-20240008