乐趣区

关于javascript:关于-varlet和const-关键字定义变量的一些归纳

const

The const declaration creates block-scoped constants, much like variables declared using the let keyword. The value of a constant can’t be changed through reassignment (i.e. by using the assignment operator), and it can’t be redeclared (i.e. through a variable declaration). However, if a constant is an object or array its properties or items can be updated or removed
常量是 块级 范畴的,十分相似用 let 语句定义的变量。但常量的值是无奈(通过从新赋值)扭转的,也不能被从新申明。文档形容

实际:

//eg1:
const a = 12
if (a) {
    const a = 10
    console.log(a)
}
console.log(a)

//console:
>10
>12
//eg2:
const a = new Object({name: 'jack'})
const b = new Object({name: 'jack'})
a.name = 'peters'
delete b.name
console.log(a,b)

//console:
> [object Object] {name: "peters"},[object Object] {...}
//eg3:
/*
数组 shift 办法用于删除数组第一个元素
数组 pop 办法用于删除数组最初一个元素
*/
const a = new Array(1)
const b = new Array(1)
a[0] = 'peters'
b.shift() //[] 后果和 pop()一样
console.log(a,b)

//console:
>["peters"],[]
key points:
  • block-scoped (块作用域)
  • value can’t be changed, and it can’t be redeclared (常量的值不可被更改,常量也不能从新 申明)
  • 在申明的同一语句中必须指定它的值 (因为申明的常量值是不可更改的)
  • However, if a constant is an object or array its properties or items can be updated or removed (const定义的常量是对象或数组时,它们的属性或者 items(数组中的一项或某项)能被赋值更新或移除(删除))

var

The var statement declares a function-scoped or globally-scoped variable, optionally initializing it to a value.

var 语句 用于申明一个 函数范畴 全局范畴 的变量,并可将其初始化为一个值(可选)文档形容

形容

var declarations, wherever they occur, are processed before any code is executed. This is called hoisting and is discussed further below.

The scope of a variable declared with var is its current execution context and closures thereof (which is either the enclosing function and functions declared within it) , or, for variables declared outside any function, global. Duplicate variable declarations using var will not trigger an error, even in strict mode, and the variable will not lose its value, unless another assignment is performed.

无论在何处申明变量,都会在执行任何代码之前进行解决。这被称为变量晋升

用 var 申明的变量的作用域是它以后的执行上下文及其闭包(嵌套函数),或者对于申明在任何函数外的变量来说是全局。应用 var 反复申明 JavaScript 变量并不会抛出谬误(即便在严格模式 (strict mode) 下),同时,变量也不会失落其值,直到调用其它的赋值操作。

hoisting (变量晋升)

Because var declarations are processed before any code is executed, declaring a variable anywhere in the code is equivalent to declaring it at the top. This also means that a variable can appear to be used before it’s declared. This behavior is called hoisting, as it appears that the variable declaration is moved to the top of the function or global code.

因为变量申明(以及其余申明)总是在任意代码执行之前解决的,所以在代码中的任意地位申明变量总是等效于在代码结尾申明。这意味着变量能够在申明之前应用,这个行为叫做“hoisting”。“hoisting”就像是把所有的变量申明挪动到函数或者全局代码的结尾地位。

实际:

//eg1:
var a = 1
if (a == 1){
    var a = 2
    console.log(a)
}
console.log(a)

//console:
>2
>2
//eg2:
function foo() {
  var x = 1;
  function bar() {
    var y = 2;
    console.log(x); // 1 (函数 `bar` 蕴含了 `x`)
    console.log(y); // 2 (`y` 在作用域内)
  }
  bar();
  console.log(x); // 1 (`x` 在作用域内)
  console.log(y); // 在严格模式(strict mode)下将抛出 ReferenceError,`y` 仅在 `bar` 函数的作用域内
}

foo();

//console:
>1
>2
>1
> "Uncaught ReferenceError: y is not defined"
//eg3:
var a, b
(function() {console.log(a)
        console.log(b)
        var a = (b = 3)
        console.log(a)
        console.log(b)
    }
)()
console.log(a)
console.log(b)

//console:
>undefined
>undefined
>3
>3
>undefined
>3
拓展释义

IIFE(立刻调用函数表达式)

这是一个被称为 自执行匿名函数 的设计模式,次要蕴含两局部。

  • 第一局部是突围在 圆括号运算符 () 里的一个匿名函数,这个匿名函数领有独立的词法作用域。这不仅防止了外界拜访此 IIFE 中的变量,而且又不会净化全局作用域。
  • 第二局部再一次应用 () 创立了一个立刻执行函数表达式,JavaScript 引擎到此将间接执行函数。

key points

  • 函数范畴 全局范畴 的变量 ==> 作用域是它以后的 执行上下文 及其 闭包(嵌套函数)
  • 并可将其初始化为一个值 ( 可选), 不初始化则为undefined
  • 变量晋升 ==> 在代码中的任意地位申明变量总是等效于在代码结尾申明

let

The let declaration declares a block-scoped local variable, optionally initializing it to a value.
let 语句申明一个块级作用域的局部变量,并能够初始化为一个值(可选)。文档形容

形容

let allows you to declare variables that are limited to the scope of a block statement, or expression on which it is used, unlike the var keyword, which declares a variable globally, or locally to an entire function regardless of block scope. The other difference between var and let is that the latter can only be accessed after its declaration is reached (see temporal dead zone). For this reason, let declarations are commonly regarded as non-hoisted.

Just like const the let does not create properties of the window object when declared globally (in the top-most scope).

An explanation of why the name “let” was chosen can be found here.

Many issues with let variables can be avoided by declaring them at the top of the scope in which they are used (doing so may impact readability).

Unlike var, let begins declarations, not statements. That means you cannot use a lone let declaration as the body of a block (which makes sense, since there’s no way to access the variable).

let 容许你申明一个 作用域被限度在块作用域中的变量 语句 或者 表达式 。与 var 关键字不同的是,var 申明的变量作用域是全局或者整个函数块的。var 和 let 的 另一个重要区别 ,let 申明的变量 不会 在作用域中 被晋升,它是在编译时才初始化(参考上面的暂时性死区)。

就像 const 一样,let 不会在全局申明时(在最顶层的作用域)创立 window 对象的属性。
能够从这里理解咱们为什么应用 let。

通过在应用 let 变量的作用域顶部申明它们,能够防止很多问题,但这样做可能会影响可读性。

与 var 不同的是,let 只是开始申明,而非一个残缺的表达式。这意味着你不能将独自的 let 申明作为一个代码块的主体(这是有情理的,因为申明的变量无奈被拜访)。

实际:

Scoping rules

let 申明的变量作用域只在其申明的块或子块外部,这一点,与 var 类似。二者之间最次要的区别在于 var 申明的变量的作用域是整个关闭函数。

//eg1:
function varTest() {
  var x = 1;
  {
    var x = 2; // same variable!
    console.log(x); // 2
  }
  console.log(x); // 2
}

function letTest() {
  let x = 1;
  {
    let x = 2; // different variable
    console.log(x); // 2
  }
  console.log(x); // 1
}

function constTest() {
    const a = 1;
    {
        const a = 2
        console.log(a)//same as the let declaration 
    }
    console.log(a)//1
}

varTest()
letTest()
constTest()

//console:
>2
>2
>2
>1
>2
>1

At the top level of programs and functions, let, unlike var, does not create a property on the global object.

在全局作用域中,let 和 var 不一样,它不会在全局对象上创立属性

var x = "global";
let y = "global";
console.log(this.x); // "global"
console.log(this.y); // undefined

在同一个函数或块作用域中反复申明同一个变量会抛出 SyntaxError

if (x) {
  let foo;
  let foo; // SyntaxError thrown.
}

switch 语句中也会触发这个谬误,因为它是同一个块作用域。

let x = 1;

switch(x) {
  case 0:
    let foo;
    break;
  case 1:
    let foo; // SyntaxError for redeclaration.
    break;
}

一个嵌套在 case 子句中的块会创立一个 新的块作用域 的词法环境,就不会产生上诉反复申明的谬误。

let x = 1;

switch(x) {
  case 0: {
    let foo;
    break;
  }
  case 1: {
    let foo;
    break;
  }
}

Temporal dead zone,TDZ (暂时性死区)

从一个代码块的开始直到代码执行到申明变量的行之前,let 或 const 申明的变量都处于“暂时性死区”中
当变量处于暂时性死区之中时,其尚未被初始化,尝试拜访变量将抛出 ReferenceError。当代码执行到申明变量所在的行时,变量被初始化为一个值。如果申明中未指定初始值,则变量将被初始化为 undefined。
与 var 申明的变量不同,如果在申明前拜访了变量,变量将会返回 undefined。以下代码演示了在应用 let 和 var 申明变量的行之前拜访变量的不同后果。

{ // TDZ starts at beginning of scope
  console.log(bar); // undefined
  console.log(foo); // ReferenceError
  var bar = 1;
  let foo = 2; // End of TDZ (for foo)
}

暂时性死区(TDZ),是 let,const 申明的变量从一个代码块(块作用域)开始执行到申明之前所处在的状态。从 var 关键字的方向来看,TDZ 的产生是因为语句执行的先后顺序产生的,var 存在变量晋升,即无论 var 定义到何处,都会将定义语句晋升到 var 作用域(函数块或执行上下文)开始之前执行(变量晋升), 所以从代码块开始执行到 let,const 语句申明之前,申明的变量都处于暂时性死区

文档形容:The term “temporal” is used because the zone depends on the order of execution (time) rather than the order in which the code is written (position). For example, the code below works because, even though the function that uses the let variable appears before the variable is declared, the function is called outside the TDZ.

应用术语“temporal”是因为区域取决于执行程序(工夫),而不是编写代码的程序(地位)。例如,上面的代码会失效,是因为即便应用 let 变量的函数呈现在变量申明之前,但函数的执行是在暂时性死区的里面。

{
  // TDZ starts at beginning of scope. TDZ 从作用域(块作用域)最开始是开始
  const func = () => console.log(letVar); // OK

  // Within the TDZ letVar access throws `ReferenceError`

  let letVar = 3; // End of TDZ (for letVar). letVar TDZ 完结
  func(); // Called outside TDZ!}

因为内部变量 foo 有值,因而会执行 if 语句块,然而因为词法作用域,该值在块内不可用:if 块内的标识符 foo 是 let foo。表达式 (foo + 55) 会抛出 ReferenceError 异样,是因为 let foo 还没实现初始化,它依然在暂时性死区里。

function test() {
  var foo = 33;
  if(foo) {let fool = (foo + 55); // ReferenceError
    console.log(fool,foo)
    // let foo = 'a'
  }
}
test();
其余状况

用在块级作用域中,let 将变量的作用域限度在块内,而 var 申明的变量的作用域是在函数内。

var a = 1;
var b = 2;

if (a === 1) {
  var a = 11; // the scope is global
  let b = 22; // the scope is inside the if-block

  console.log(a);  // 11
  console.log(b);  // 22
}

console.log(a); // 11
console.log(b); // 2

然而,var 与 let 合并的申明形式会抛出 SyntaxError 谬误,因为 var 会将变量晋升至块的顶部,这会导致隐式地反复申明变量。

let x = 1;

{var x = 2; // SyntaxError for re-declaration}

key Points

  • 块级作用域的 局部变量
  • Just like const the let does not create properties of the window object when declared globally (in the top-most scope).

tidy

let var const
作用域 块级作用域 执行上下文或函数范畴(var 语句 用于申明一个函数范畴或全局范畴的变量) 全局或本地申明的块
被申明的变量值特点 可更改值的变量 可更改值的变量 常量且不可更改(初始化必须指定值)
变量申明语句所在的作用域内 反复申明 同一变 / 常量 不可反复申明 能够反复申明 不可反复申明


参考资料:MDN

退出移动版