企业网站,个人博客等WordPress网站以及其他语言网站开发定制需求加QQ详聊。

了解javascript ES6中的let和const

JavaScript笔记 码云 28℃ 0评论
目录
[隐藏]

在过去的两年中,ES6已被我们广泛地用于程序开发中,在本教程中,我将通过重述我们大多数人在JavaScript中学到的第一件事——定义变量和占位符,将您带入JavaScript ES6的美妙世界。

了解javascript ES6中的let和const

定义变量的两种新方法—let和const

关键字一直是我们在JavaScript中定义变量的方式。然而,在JavaScript ES6中,用两个新的关键字来更好地表示存储的数据类型,从而使它们更容易调试,更不容易出错。它们是:

  • let
  • const

首先要理解的是,let和const是块作用域,而var则是函数作用域。这意味着它们是在最接近的块(花括号)中定义的,在这里,当var在整个函数中是本地的,或者在定义外部函数时是全局的。

let和const之间的区别在于,前者应该用于保存可能发生变化的变量,而const,顾名思义,则是保存我们所知道的不变的数据。实际上,试图在设置const值之后重置它将导致错误。

关键字let

当所持有的数据可能发生变化时,使用let去声明一个变量,类似var:

let myage = 39
if (new Date().getFullYear == 2018){
myage = 40
}

如上所见,一旦我使用let定义了一个变量,我就可以通过使用新值再次引用它来更新它的值,而不需要在它前面使用let关键字。与var不同的是,您不能在块内多次定义同一个let变量:

let myage = 39
let myname = 'George'
let myage = 40  //SyntaxError:标识符myage已经声明

这有助于防止我们在声明变量之后意外重写变量,在使用var时这种情况太频繁了。之前我们已经讨论过了,让它块作用域,这意味着它可以在块(包括内部块)中定义,但不在它外面:

if (true){ 
// 定义新的块
let myname = 'George'
}

console.log(myname) //语法错误,myname未定义

相比之下,如果我们使用var关键字:

if (true){ // 新建块
    var myname = 'George'
}
console.log(myname) // 输出 'George'

在var中,变量的作用域限定在函数的作用域上,或者在函数外部(如上面的示例),限定在窗口对象本身。

定义具有相同名称的多个let变量

虽然我们不能在一个块中多次定义同一个let变量,但是没有什么可以阻止我们在另一个块中这样做。需要记住的是,ES6脚本将它们视为独立的变量:

let mybrother = 'Paul'
if (true){ // 新建块
let mybrother = 'Jason'
console.log(mybrother) // Jason
}
console.log(mybrother) // Paul

上面的例子中我们使用let声明mybrother两次,每个块中一次,这是有效的。每一个mybrother变量都是不同于另一个的,这表明,let声明的变量只在它所在的代码块有效。如果我们替换成var,console.log()会在两个实例中返回“Jason”,因为第二个var声明会在遇到“jamie”时重写第一个值。

用let作为for循坏

在JavaScript中用(var;;)循环,使用let代替var迭代跟踪提供了一个独特的优势——在每次循坏中我们不再需要使用立即调用函数表达式内循环正确捕获迭代变量的值,我们应该需要这些值。

考虑传统的for循环,该循环试图在循环运行时间之后调用迭代变量的值,例如使用setTimeout:

for (var i = 0; i < 5; i++){
setTimeout(function(){ 
console.log(i) 
}, i * 100)}
//输出 '5, 5, 5, 5, 5'

这个失败了,你得到的就是我在最后一次迭代的值,不是0 1 2 3 4。问题是,var变量的作用域不是它所在的块,因此可以在任何地方访问,无论是在它所定义的函数内部,还是在函数外部。这意味着在for循环中重复重写变量i。当setTimeout试图调用i时,它得到的是我设置的最后一个值。

在过去,克服这个麻烦问题的一种常见方法是在for循环中加入一个立即调用函数表达式,创建一个闭包,在每次迭代中捕获i的值:

for (var i = 0; i < 5; i++){ 
(function(x){ 
setTimeout(function(){
console.log(x) 
}, i * 100) })(i)}
//logs '0, 1, 2, 3, 4'

使用let替换var可以自动解决这个常见问题,因为迭代变量使用let将i的每个实例都限定到它所在的块中,创建与在for循环中包装立即调用函数表达式相同的结果:

for (let i = 0; i < 5; i++){
    setTimeout(function(){
        console.log(i)
    }, i * 100)
}
//'0, 1, 2, 3, 4'

无论延迟是什么,i的正确值都会被返回。这在许多场景中都很有用,比如在循环中依赖于i的值来生成不同请求的Ajax请求,或者利用i的值执行针对其绑定到的元素的操作的事件处理程序。下面是后面的一个例子:

let links = document.getElementsByTagName('a');
for (let i=0; i<links.length; i++){
links[i].onclick = function(){ 
alert('You clicked on link ' + (i+1));
}};

暂时性死区

在代码块内,使用let命令声明变量之前,该变量都是不可用的。这在语法上,称为“暂时性死区”(temporal dead zone,简称 TDZ)。在该区域中,尝试引用让变量返回一个ReferenceError:

function test(){
    console.log(dog) // 返回 ReferenceError
    let dog = 'spotty'
}

这似乎是显而易见的,但是传统上,由于变量提升的概念,var变量的行为非常不同。简单地说,使用var定义的变量会自动“挂起”到执行上下文的最顶端(例如:如果是全局变量,则在函数的顶部或脚本的顶部),即使它是在块的更远处初始化的。这意味着你可以在变量实际声明之前引用它,而不会得到一个ReferenceError:

function test(){
console.log(dog) //返回未定义
var dog = 'spotty' 
console.log(dog) // ‘spotty’
}

将返回未定义的值,因为提升只将变量本身移动到顶部,而不是将其设置为的值。由于变量提升,上述情况相当于:

function test(){
var dog console.log(dog) //返回未定义
var dog = 'spotty'
console.log(dog) // ‘spotty’}

对于let变量,不涉及变量提升,在块中物理声明一个let变量之前尝试引用它将返回一个ReferenceError。

ES6 规定暂时性死区和let、const语句不出现变量提升,主要是为了减少运行时错误,防止在变量声明前就使用这个变量,从而导致意料之外的行为。这样的错误在 ES5 是很常见的,现在有了这种规定,避免此类错误就很容易了。

总之,暂时性死区的本质就是,只要一进入当前作用域,所要使用的变量就已经存在了,但是不可获取,只有等到声明变量的那一行代码出现,才可以获取和使用该变量。

const关键字

我们花了很多时间讨论let这个关键字,但是我们不要忘记它可靠的一面,const。

使用const来声明不会更改的变量,例如PI的值或兄弟的名称。当开发团队中的另一个成员在您的代码中看到const关键字时,他/她知道这是一个更少的变量,他必须跟踪更改。

const在块作用域类似于let,使它只能在它所定义的块(花括号)中访问。此外,它还受暂时性死区规则的影响。

与let不同的是,在定义时必须使用值进行初始化。此外,它不能被重新分配到另一个值之后:

const mydog = 'spotty' // 正确
mydog = 'fluffy' // error:赋值为常数
const mybrother // error: const中缺少初始化器

虽然const变量不能完全重新分配到一个不同的值,如果const的值是一个对象或数组,对象的属性本身仍然是可变的,可以修改:

const myobject = {name:'George', age:39}
//myobject = {name: 'Ken', age:39} //error
myobject.age = 40 // OK
 
const myarray = []
myarray[0] = 'Football' // OK

let和const与var

既然大家已经掌握了如何使用let和const,那么问题就变成了,是否应该开始完全在代码中使用let和const替换var ?关于这一点,有许多流派的观点,尽管我同意这样的观点:一般来说,var现在应该被视为最弱的,在使用let和const的情况结束后使用。你怎么看?

转载请注明:码云笔记 » 了解javascript ES6中的let和const

喜欢 (1)or分享 (0)
发表我的评论
取消评论
表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址