博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
何时在JavaScript中使用var vs let vs const
阅读量:2522 次
发布时间:2019-05-11

本文共 15576 字,大约阅读时间需要 51 分钟。

In this post you'll learn two new ways to create variables in JavaScript (ES6), let and const. Along the way we'll look at the differences between var, let, and const as well as cover topics like function vs block scope, variable hoisting, and immutability.

在本文中,您将学习letconst两种在JavaScript(ES6)中创建变量的新方法。 在此过程中,我们将研究varletconst之间的区别,并涵盖诸如函数与块作用域,变量提升和不变性之类的主题。

ES2015 (or ES6) introduced two new ways to create variables, let and const. But before we actually dive into the differences between var, let, and const, there are some prerequisites you need to know first. They are variable declarations vs initialization, scope (specifically function scope), and hoisting.

ES2015(或ES6)引入了两种创建变量的新方法letconst 。 但是,在我们实际研究varletconst之间的差异之前,您需要首先了解一些先决条件。 它们是变量声明与初始化,作用域(特别是函数作用域)和提升。

变量声明与初始化 (Variable Declaration vs Initialization)

A variable declaration introduces a new identifier.

变量声明引入了新的标识符。

var declaration

Above we create a new identifier called declaration. In JavaScript, variables are initialized with the value of undefined when they are created. What that means is if we try to log the declaration variable, we'll get undefined.

在上面,我们创建一个称为声明的新标识符。 在JavaScript中,变量在创建时会使用undefined的值进行初始化。 这意味着如果我们尝试记录declaration变量,则会得到undefined

var declarationconsole.log(declaration) // undefined

So if we log the declaration variable, we get undefined.

因此,如果我们记录声明变量,则会得到未定义。

In contract to variable declaration, variable initialization is when you first assign a value to a variable.

按照变量声明的约定,变量初始化是您首次为变量分配值时。

var declarationconsole.log(declaration) // undefineddeclaration = 'This is an initialization'

So here we're initializing the declaration variable by assigning it to a string.

因此,这里我们通过将declaration变量分配给字符串来初始化它。

This leads us to our second concept, Scope.

这就引出了我们的第二个概念,范围。

范围 (Scope)

Scope defines where variables and functions are accessible inside of your program. In JavaScript, there are two kinds of scope - global scope, and function scope. According to the official spec,

范围定义了在程序内部可访问变量和函数的位置。 在JavaScript中,有两种作用域- 全局作用域函数作用域 。 根据官方规范,

"If the variable statement occurs inside a FunctionDeclaration, the variables are defined with function-local scope in that function.".

“如果变量语句出现在FunctionDeclaration内部,则在该函数中使用局部函数作用域定义变量。”

What that means is if you create a variable with var, that variable is "scoped" to the function it was created in and is only accessible inside of that function or, any nested functions.

这就是说,如果您使用var创建变量,则该变量将“作用域”到创建该函数的函数,并且只能在该函数或任何嵌套函数内部访问。

function getDate () {  var date = new Date()  return date}getDate()console.log(date) // ❌ Reference Error

Above we try to access a variable outside of the function it was declared. Because date is "scoped" to the getData function, it's only accessible inside of getDate itself or any nested functions inside of getDate (as seen below).

上面我们尝试在声明的函数之外访问变量。 因为date是“作用域”到getData功能,它是唯一能够内部getDate本身或内部的任何嵌套函数getDate (如下图所示)。

function getDate () {  var date = new Date()  function formatDate () {    return date.toDateString().slice(4) // ✅   }  return formatDate()}getDate()console.log(date) // ❌ Reference Error

Now let's look at a more advanced example. Say we had an array of prices and we needed a function that took in that array as well as a discount and returned us a new array of discounted prices. The end goal might look something like this.

现在让我们看一个更高级的例子。 假设我们有一个prices数组,我们需要一个函数,该函数接受该数组以及discount ,并为我们返回新的折扣价格数组。 最终目标可能看起来像这样。

discountPrices([100, 200, 300], .5) // [50, 100, 150]

And the implementation might look something like this

实现可能看起来像这样

function discountPrices (prices, discount) {  var discounted = []  for (var i = 0; i < prices.length; i++) {    var discountedPrice = prices[i] * (1 - discount)    var finalPrice = Math.round(discountedPrice * 100) / 100    discounted.push(finalPrice)  }  return discounted}

Seems simple enough but what does this have to do with block scope? Take a look at that for loop. Are the variables declared inside of it accessible outside of it? Turns out, they are.

看起来很简单,但这与块作用域有什么关系? 看一下for循环。 在其内部声明的变量是否可以在其外部访问? 原来是。

function discountPrices (prices, discount) {  var discounted = []  for (var i = 0; i < prices.length; i++) {    var discountedPrice = prices[i] * (1 - discount)    var finalPrice = Math.round(discountedPrice * 100) / 100    discounted.push(finalPrice)  }  console.log(i) // 3  console.log(discountedPrice) // 150  console.log(finalPrice) // 150  return discounted}

If JavaScript is the only programming language you know, you may not think anything of this. However, if you're coming to JavaScript from another programming language, specifically a programming language that is blocked scope, you're probably a little bit concerned about what's going on here. It's not really broken, it's just kind of weird. There's not really a reason to still have access to i, discountedPrice, and finalPrice outside of the for loop. It doesn't really do us any good and it may even cause us harm in some cases. However, since variables declared with var are function scoped, you do.

如果JavaScript是您所知道的唯一编程语言,那么您可能对此一无所知。 但是,如果您是从另一种编程语言(特别是受限制范围的编程语言)使用JavaScript的,那么您可能会有点担心这里发生的事情。 它并没有真正坏掉,只是有点奇怪。 确实没有理由仍然可以在for循环之外访问idiscountedPricefinalPrice 。 它实际上并没有给我们带来任何好处,在某些情况下甚至可能导致我们受到伤害。 但是,由于用var声明的变量是函数作用域的,所以您可以这样做。

Now that we've discussed variable declarations, initializations, and scope, the last thing we need to flush out before we dive into let and const is hoisting.

既然我们已经讨论了变量声明,初始化和作用域,那么在深入研究letconst之前,我们需要清除的最后一件事。

吊装 (Hoisting)

Remember earlier we said that "In JavaScript, variables are initialized with the value of undefined when they are created.". Turns out, that's all that "Hoisting" is. The JavaScript interpreter will assign variable declarations a default value of undefined during what's called the "Creation" phase.

还记得前面我们说过的:“在JavaScript中,变量在创建时会用undefined值初始化。” 事实证明,这就是“吊装”的全部内容。 JavaScript解释器将在“创建”阶段为变量声明分配默认值undefined

For a much more in depth guide on the Creation Phase, Hoisting, and Scopes see

有关创建阶段,提升和合并范围的更深入的指导,请参阅

Let's take a look at the previous example and see how hoisting affects it.

让我们看一下前面的示例,看看提升如何影响它。

function discountPrices (prices, discount) {  var discounted = undefined  var i = undefined  var discountedPrice = undefined  var finalPrice = undefined  discounted = []  for (var i = 0; i < prices.length; i++) {    discountedPrice = prices[i] * (1 - discount)    finalPrice = Math.round(discountedPrice * 100) / 100    discounted.push(finalPrice)  }  console.log(i) // 3  console.log(discountedPrice) // 150  console.log(finalPrice) // 150  return discounted}

Notice all the variable declarations were assigned a default value of undefined. That's why if you try access one of those variables before it was actually declared, you'll just get undefined.

注意,所有变量声明都被分配了默认值undefined 。 这就是为什么如果您在实际声明变量之前尝试访问其中一个变量则只会得到undefined

function discountPrices (prices, discount) {  console.log(discounted) // undefined  var discounted = []  for (var i = 0; i < prices.length; i++) {    var discountedPrice = prices[i] * (1 - discount)    var finalPrice = Math.round(discountedPrice * 100) / 100    discounted.push(finalPrice)  }  console.log(i) // 3  console.log(discountedPrice) // 150  console.log(finalPrice) // 150  return discounted}

Now that you know everything there is to know about var, let's finally talk about the whole point of why you're here, what's the difference between var, let, and const?

既然您已经了解了有关var所有知识,那么让我们最后谈谈您为什么在这里的全部要点, varletconst什么区别?

var VS让VS const (var VS let VS const)

First, let's compare var and let. The main difference between var and let is that instead of being function scoped, let is block scoped. What that means is that a variable created with the let keyword is available inside the "block" that it was created in as well as any nested blocks. When I say "block", I mean anything surrounded by a curly brace {} like in a for loop or an if statement.

首先,让我们比较varletvarlet之间的主要区别在于, let是块范围的,而不是函数范围的。 这意味着用let关键字创建的变量在创建的“块”以及任何嵌套块中都可用。 当我说“ block”时,是指用花括号{}包围的所有内容,例如for循环或if语句。

So let's look back to our discountPrices function one last time.

因此,让我们最后一次回顾我们的discountPrices函数。

function discountPrices (prices, discount) {  var discounted = []  for (var i = 0; i < prices.length; i++) {    var discountedPrice = prices[i] * (1 - discount)    var finalPrice = Math.round(discountedPrice * 100) / 100    discounted.push(finalPrice)  }  console.log(i) // 3  console.log(discountedPrice) // 150  console.log(finalPrice) // 150  return discounted}

Remember that we were able to log i, discountedPrice, and finalPrice outside of the for loop since they were declared with var and var is function scoped. But now, what happens if we change those var declarations to use let and try to run it?

请记住,我们可以登录idiscountedPricefinalPrice外面for循环,因为他们与申报varvar的功能范围的。 但是现在,如果我们更改这些var声明以使用let并尝试运行它会发生什么?

function discountPrices (prices, discount) {  let discounted = []  for (let i = 0; i < prices.length; i++) {    let discountedPrice = prices[i] * (1 - discount)    let finalPrice = Math.round(discountedPrice * 100) / 100    discounted.push(finalPrice)  }  console.log(i) // 3  console.log(discountedPrice) // 150  console.log(finalPrice) // 150  return discounted}discountPrices([100, 200, 300], .5) // ❌ ReferenceError: i is not defined

?‍♀️ We get ReferenceError: i is not defined. What this tells us is that variables declared with let are block scoped, not function scoped. So trying to access i (or discountedPrice or finalPrice) outside of the "block" they were declared in is going to give us a reference error as we just barely saw.

We️我们得到ReferenceError: i is not defined 。 这告诉我们,用let声明的变量是块范围的,而不是函数范围的。 因此,试图访问i (或discountedPricefinalPrice )之外他们是想给大家一个参考的错误,因为我们只是勉强锯被宣布的“块”的。

var VS letvar: function scopedlet: block scoped

The next difference has to do with Hoisting. Earlier we said that the definition of hoisting was "The JavaScript interpreter will assign variable declarations a default value of undefined during what's called the 'Creation' phase." We even saw this in action by logging a variable before it was declared (you get undefined)

下一个差异与起重有关。 之前我们说过,提升的定义是“ JavaScript解释器将在“创建”阶段为变量声明分配默认值undefined 。 我们甚至通过在声明变量之前记录变量来看到这一点(实际上是undefined )

function discountPrices (prices, discount) {  console.log(discounted) // undefined  var discounted = []  for (var i = 0; i < prices.length; i++) {    var discountedPrice = prices[i] * (1 - discount)    var finalPrice = Math.round(discountedPrice * 100) / 100    discounted.push(finalPrice)  }  console.log(i) // 3  console.log(discountedPrice) // 150  console.log(finalPrice) // 150  return discounted}

I can't think of any use case where you'd actually want to access a variable before it was declared. It seems like throwing a ReferenceError would be a better default than returning undefined. In fact, this is exactly what let does. If you try to access a variable declared with let before it's declared, instead of getting undefined (like with those variables declared with var), you'll get a ReferenceError.

我想不出任何用例,您实际上要在声明变量之前访问它。 似乎抛出ReferenceError比返回undefined更好。 实际上,这正是let所做的。 如果尝试在声明之前访问用let声明的变量,而不是获取undefined变量(如使用var声明的变量),则将得到ReferenceError。

function discountPrices (prices, discount) {  console.log(discounted) // ❌ ReferenceError  let discounted = []  for (let i = 0; i < prices.length; i++) {    let discountedPrice = prices[i] * (1 - discount)    let finalPrice = Math.round(discountedPrice * 100) / 100    discounted.push(finalPrice)  }  console.log(i) // 3  console.log(discountedPrice) // 150  console.log(finalPrice) // 150  return discounted}
var VS letvar:   function scoped  undefined when accessing a variable before it's declaredlet:   block scoped  ReferenceError when accessing a variable before it's declared

让VS const (let VS const)

Now that you understand the difference between var and let, what about const? Turns out, const is almost exactly the same as let. However, the only difference is that once you've assigned a value to a variable using const, you can't reassign it to a new value.

既然您已经了解了varlet之间的区别,那么const呢? 事实证明, constlet几乎完全相同。 但是,唯一的区别是,一旦使用const将值分配给变量后,就无法将其重新分配给新值。

let name = 'Tyler'const handle = 'tylermcginnis'name = 'Tyler McGinnis' // ✅handle = '@tylermcginnis' // ❌ TypeError: Assignment to constant variable.

The take away above is that variables declared with let can be re-assigned, but variables declared with const can't be.

上面的要点是,可以重新分配用let声明的变量,但不能重新分配用const声明的变量。

Cool, so anytime you want a variable to be immutable, you can declare it with const. Well, not quite. Just because a variable is declared with const doesn't mean it's immutable, all it means is the value can't be re-assigned. Here's a good example.

很酷,因此任何时候只要您希望变量是不可变的,都可以使用const声明它。 好吧,不完全是。 仅仅因为用const声明了一个变量并不意味着它是不可变的,而是意味着该值不能被重新分配。 这是一个很好的例子。

const person = {  name: 'Kim Kardashian'}person.name = 'Kim Kardashian West' // ✅person = {} // ❌ Assignment to constant variable.

Notice that changing a property on an object isn't reassigning it, so even though an object is declared with const, that doesn't mean you can't mutate any of its properties. It only means you can't reassign it to a new value.

请注意,更改对象的属性不会重新分配它,因此,即使使用const声明了对象,也不意味着您无法更改其任何属性。 这仅意味着您无法将其重新分配为新值。



Now the most important question we haven't answered yet, should you use var, let, or const? The most popular opinion, and the opinion that I subscribe to, is that you should always use const unless you know the variable is going to change. The reason for this is by using const, you're signalling to your future self as well as any other future developers that have to read your code that this variable shouldn't change. If it will need to change (like in a for loop), you should use let.

现在,我们尚未回答的最重要的问题是,您应该使用varlet还是const ? 最受欢迎的观点以及我赞成的观点是,除非您知道变量将要更改,否则应始终使用const 。 这样做的原因是通过使用const ,您可以向将来的自己以及其他任何必须阅读此代码不应更改此代码的将来的开发人员发出信号。 如果需要更改(例如在for循环中),则应使用let

So between variables that change and variables that don't change, there's not much left. That means you shouldn't ever have to use var again.

因此,在变化的变量和不变的变量之间,剩下的不多了。 这意味着您不必再使用var

Now the unpopular opinion, though it still has some validity to it, is that you should never use const because even though you're trying to signal that the variable is immutable, as we saw above, that's not entirely the case. Developers who subscribe to this opinion always use let unless they have variables that are actually constants like _LOCATION_ = ....

现在,尽管它仍然具有一定的有效性,但不受欢迎的观点是,您永远不应该使用const因为即使您试图像上面那样看到信号变量是不可变的,也不完全是这种情况。 订阅此意见的开发人员始终使用let除非他们具有实际上是常量的变量,例如_LOCATION_ = ...

So to recap, var is function scoped and if you try to use a variable declared with var before the actual declaration, you'll just get undefined. const and let are blocked scoped and if you try to use variable declared with let or const before the declaration you'll get a ReferenceError. Finally the difference between let and const is that once you've assigned a value to const, you can't reassign it, but with let, you can.

因此,回顾一下, var是函数范围的,如果尝试在实际声明之前使用var声明的变量,则只会得到undefinedconstlet被限制作用域,如果您尝试在声明之前使用letconst声明的变量,则会得到ReferenceError。 最后, letconst之间的区别在于,一旦您为const分配了一个值,就无法重新分配它,但是使用let可以。

var VS let VS constvar:   function scoped  undefined when accessing a variable before it's declaredlet:   block scoped  ReferenceError when accessing a variable before it's declaredconst:  block scoped  ReferenceError when accessing a variable before it's declared  can't be reassigned

这是我们的 。 如果您喜欢这篇文章,请查看。 (This is part of our . If you enjoyed this post, check it out.)

翻译自:

转载地址:http://eywzd.baihongyu.com/

你可能感兴趣的文章
企业帐号进行IPA的打包、分发、下载安装的详细流程(转载)
查看>>
《项目架构那点儿事》——快速构建Junit用例
查看>>
{"errmsg":"invalid weapp pagepath hint: [IunP8a07243949]","errcode":40165}微信的坑
查看>>
DB2V9.5数据库使用pdf
查看>>
Java Bigdecimal使用
查看>>
SQL注入之绕过WAF和Filter
查看>>
jquery validate使用方法
查看>>
DataNode 工作机制
查看>>
windows系统下安装MySQL
查看>>
错误提示总结
查看>>
实验二+070+胡阳洋
查看>>
Linux IPC实践(3) --具名FIFO
查看>>
Qt之模拟时钟
查看>>
第一次接触安卓--记于2015.8.21
查看>>
(转)在分层架构下寻找java web漏洞
查看>>
mac下多线程实现处理
查看>>
C++ ifstream ofstream
查看>>
跟初学者学习IbatisNet第四篇
查看>>
seL4环境配置
查看>>
Git报错:insufficient permission for adding an object to repository database .git/objects
查看>>