微信号:gh_15d32a71b93c

介绍:介绍各种前端技巧,帮助提高前端开发的速度,逐渐做到分分钟完成开发.

理解JavaScript中的提升

2017-03-08 10:46 web前端程序员

Python部落(python.freelycode.com)组织翻译,禁止转载,欢迎转发。

一个快速和简洁的描述---JavaScript提升机制

在本教程中,我们将探讨著名的变量提升机制在JavaScript中是如何发生的。 在我们开始之前,让我们先来了解什么是变量提升。

Hoisting是一种JavaScript机制,其中在代码执行之前将变量和函数声明移动到其作用域的顶部。

不可避免地,这意味着无论函数和变量何处被声明,无论它们的范围是全局还是局部,它们都被移动到它们的作用域的顶部。

然而,值得注意的是,提升机制只移动声明,分配留在原地。

如果你曾经想过为什么你能够在你的代码中编写函数之前调用函数,然后再阅读你就能收获更多!

#未定义与引用异常

在我们认真开始之前,让我们来考虑几件事情。

第一点:

在JavaScript中,未声明的变量在执行时被赋值为未定义的值,并且类型为未定义。

第二点:

在JavaScript中,试图访问一个之前未声明的变量时会抛出引用异常。

JavaScript处理变量时的行为由于提升而变得微妙。 我们将在后面的章节深入讨论这一点。

#变量提升

以下是JavaScript生命周期和变量声明和初始化发生的指示顺序。

但是,由于JavaScript允许我们声明的同时初始化我们的变量,这是最常用的模式:

然而要记住的是,在后台,JavaScript会先郑重地声明,然后再初始化我们的变量。

正如我们之前提到的,所有的变量和函数声明被提升到它们的作用域的顶部。 我还应该在代码执行之前添加一些东西来处理变量声明。

然而相反,未声明的变量不存在,直到代码执行时才分配。 因此,当执行赋值时,为未声明的变量会被赋值为一个全局变量。 这意味着,所有未声明的变量都是全局变量。

要演示此行为,请查看以下内容:

由于这是JavaScript处理变量的一个奇怪之处,因此始终建议先声明变量,而不管它们是在函数内还是全局范围内。 这清楚地告诉了解释器应该如何在运行时处理它们。

#ES5版本

VAR关键字

使用关键字var声明的变量的范围是在其当前执行的上下文范围。 这是封闭函数或者在任何函数,全局之外声明的变量。 让我们来看几个例子来说明:

全局变量

我们期望日志的结果是:ReferenceError:hoist is not defined,但是其输出undefined。

为什么会这样呢?

这个发现使我们更接近我们的答案。

JavaScript已经提升了变量声明。 上面的代码看起来像解释器:

因此,我们可以在声明它们之前使用变量。 然而,我们必须小心,因为提升的变量被初始化的值是未定义的。 最好的选择是在使用前声明和初始化我们的变量。

函数作用域的变量

如上所述,全局范围内的变量被提升到作用域的顶部。 接下来,让我们看看函数作用域变量是如何提升的。

对我们的输出一个有根据的猜测。

如果你猜未定义,你是对的。 如果你没有猜到,不要担心,我们很快就能知道真相。

这是解释器如何查看上面的代码:

var声明message变量的范围为hoist(),但被提升到函数的顶部。

为了避免这个陷阱,我们将确保在使用变量之前声明和初始化变量:

严格模式

得益于JavaScript的es5版本的实用程序strict-mode,我们可以更谨慎地声明我们的变量。 通过启用strict mode,我们选择JavaScript的一个变种限制,在声明之前不会容忍变量的使用情况。

在strict mode 下执行我们的代码:

1.通过将它们更改为显式抛出错误来消除一些隐藏的JavaScript错误,这些错误将由解释器抛出。

2.修复错误,使JavaScript引擎难以执行优化。

3.禁止一些可能在JavaScript的未来版本的中定义语法。

我们在前面的文件或函数中启用strict mode来检验下。

我们可以看到,假设我们忘了声明我们的变量,use strict将会阻止我们,在我们的轨道中显式抛出一个引用异常。 试试看,没有使用strict,看看会发生什么。

Strict mode在不同的浏览器中行为不同,因此建议在开发中在对它形成依赖之前要彻底地执行特征测试。

#ES6版本

本文写于2017年1月时ECMAScript 6和ECMAScript 2015被称为ES6是ECMAScript标准的最新版本,并介绍了对es5的一些改进。

我们感兴趣的是标准的变化如何影响JavaScript变量的声明和初始化。

LET关键字

在我们开始之前,要注意的是,使用关键字let声明的变量的作用域是块作用域,而不是函数作用域。 这很重要,但它不应该在这里麻烦我们。 但是,简单地说,它只是意味着变量的范围被绑定到声明它的块,而不是声明它的函数。

让我们从let关键字的行为开始。

像之前一样,对于var关键字,我们期望日志的输出未定义。 然而,由于es6 let不使用未声明的变量,解释器显式地抛出一个引用错误。

这确保我们总是首先声明我们的变量。

但是,在这里我们还是要小心。 像下面这样的实现方式将导致未定义的输出,而不是引用异常。

因此,为了谨慎起见,我们应该先声明,然后在使用它们之前为我们的变量赋值一个值。

常量

在es6中引入了const关键字允许不可变变量。 也就是说,一旦赋值,其值不能被修改的变量。

使用const,和let一样,变量被提升到块的顶部。

让我们看看,如果我们尝试重新赋值一个const变量的值会发生什么。

 让我们来看看,const如何修改变量声明?

很多像let关键字,解释器不是抛出未定义,而是通过显式抛出一个引用异常来提示我们。

当在函数中使用const时也会发生同样的情况。

使用const,es6进一步。 如果我们在声明和初始化之前使用常量,解释器会抛出一个错误。

我们的Linter也很快通知我们这种重要错误:

全局地,

因此,常量变量必须在使用前声明和初始化。

作为本节的序言,需要注意的是,JavaScript的es6 let和const提升变量声明。 在这种情况下来区别它们是如何初始化的。 用let和const声明的变量在执行开始时保持未初始化,而用var声明变量,用未定义的值初始化。

#函数提升

JavaScript函数可以简单地分为如下:

1.函数声明

2.函数表达式

我们将研究提升是如何受这两种函数类型影响的。

函数声明

以下这些形式都是被完全提升到顶部。 现在,我们可以理解为什么JavaScript使我们能够在声明之前调用一个函数。

函数表达式

函数表达式是不被提升的。

让我们尝试一个函数声明和表达式的组合。

正如我们在上面看到的,变量声明var expression被提升,但是赋值给一个函数就不行。 因此,解释器抛出一个TypeError,因为它将expression()当成一个变量而不是一个函数。

#优先顺序

在声明JavaScript函数和变量时,要记住一些事情很重要。

1.变量赋值优先于函数声明

2.函数声明优先于变量声明

函数声明是通过变量声明提升的,而不是通过变量赋值。

让我们来看看这个行为有什么含义。

变量赋值优先于函数声明


函数声明优先于变量声明


即使我们变化了声明的位置,JavaScript解释器仍然会先考虑double 类型函数。

#类的提升

JavaScript类也可以简单地分为:

1.类声明

2.类表达式

类声明

就像函数同行,JavaScript类声明被提升。 然而,他们仍然处于未初始化状态,直到评估。 这意味着你必须先声明一个类,然后才能使用它。

我相信你已经注意到,我们不是得到一个未定义,而是得到一个引用异常。 这些证据为我们的立场类声明被提升提供了证明。

你会注意到你的linter,它已经为我们提供了一个提示。

所以,只要需要使用到类声明,访问类声明,你必须先声明。

类表达式

就像函数同行,类表达式不被提升。

下面是一个使用类表达式的未命名或匿名变体的示例。

这里有一个命名类表达式的例子。

正确的做法是这样的:

#警告

有一个关于Javascript es6 let的参数,const变量和类确切被提升,粗略提升或不提升。 有些人认为,他们实际上是被提升但未初始化,而有些人认为他们根本没有被提升。

#总结

让我们总结一下我们到目前为止所学到的:

1.在使用es5 var时,试图使用未声明的变量将导致该变量在提升时被赋值为未定义。

2.在使用es6 let和const时,使用未声明的变量将导致引用异常,因为变量在执行时保持未初始化。

因此,

1.我们应该习惯在使用前声明和初始化JavaScript变量。

2.在JavaScript es5中使用strict mode可以帮助暴露未声明的变量。

我希望这篇文章能对JavaScript的提升概念有一个良好的介绍,并刺激你对JavaScript语言产生的微妙的兴趣。

我们讨论的代码可以在这里找到。


英文原文:https://scotch.io/tutorials/understanding-hoisting-in-javascript
译者:萧秋兰


 
web前端程序员 更多文章 使用CSS网格布局放置元素的7种方法 关于Javascript的一些细微优化 RxJS的动画介绍(上) 50个AJAX面试问答 如何在Reactjs中进行简单的表单验证
猜您喜欢 如何成为一位数据科学家——Peter Harrington专访 微信小程序发布时间出炉!全面了解小程序的前世今生 谈一谈越来越难做的前端 用Redis实现锁机制的简单方法 这是什么?JAVA!互联网的未来..........