每周获取最新的 Wordpress 资源

ES6 新特性:使用 let 和 const 定义变量

前言

2017年 WordPress 的开发可能发生很多变化,Wordpress 已经有越来越完善的 Rest API,学习一些 Javascript,开发一些 Javascript WordPress Theme,势在必行。

很长时间以来使用 javascript 定义变量一直只有一种方式,那就是 var,现在在 ES6 的语法中,可以使用 constlet 来定义变量,使用方式语法当然和 var 是差不多的,但是它们各自应该在什么样的情境下使用呢?

使用 const 创建不可改变的变量

const 声明创建一个只读的常量。这不意味着常量指向的值不可变,而是变量标识符的值只能赋值一次。( JavaScript 中的常量和 Java,C++ 中的常量一个意思。注意区分常量的值和常量指向的值的不同)。

也就是说当你使用 const 声明了一个常量,然后对它重复赋值,这时 javascript 就会报错。我们可以在全局作用域或者函数内声明常量,常量需要被初始化。这就是说,在定义常量的同时必须初始化(这是有意义的,鉴于变量的值在初始化后就不能改变)。

同时,常量拥有块作用域,这和使用 let 定义的变量十分相似。不过常量的值不能通过再赋值改变,也不能再次声明。

还有要注意的是,一个常量不能和它所在作用域内的其他变量或函数拥有相同的名称。反过来说,不在其作用域内就可以。

如下面的代码就是没有问题的:

const pi = 3.14259;

function pi_round(){

    const pi = 3.14;

    return pi;

}

数组和对象使用常量声明

如果我们使用 const 把一个数组和对象声明成常量又会发生什么呢?

看下面的代码,我们用 const 声明数组和对象:

const days = ["Monday"];
const person = {
    first_name: "Jim";
}

现在我们分别给数组和对象增加成员:

days.push("Tuesday");
person.last_name = "Green";

猜会怎么样?会报错?No,一切运作正常,它们的值也会正常改变。所以说像数组元素和对象属性方法并不在保护的范围内,修改不会报错,但是一旦重写覆盖了就会报错。比如:

// 会报错
person = {
    first_name: Andrew
}

使用 let 定义变量

let 声明了一个块级域的局部变量,并且可以给它一个初始化值。

let 允许把变量的作用域限制在块级域中。与 var 不同处是:var 声明变量要么是全局的,要么是函数级的,而无法是块级的。

let 的暂存死区与错误

在同一个函数或同一个作用域中用 let 重复定义一个变量将引起 TypeError.

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

在 ECMAScript 2015 中, let 将会提升这个变量到语句块的顶部。然而,在这个语句块中,在变量声明之前引用这个变量会导致一个 ReferenceError 的结果, 因为 let 变量 在"暂存死区" (从块的开始到声明这段).

function do_something() {
  console.log(foo); // ReferenceError
  let foo = 2;
}

switch 声明中你可能会遇到这样的错误,因为一个 switch 只有一个作用块.

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

  case 1:
    let foo; // TypeError for redeclaration.
    break;
}

let 后跟一个函数传递的参数时将导致循环内部报错。

function go(n){
  for (let n of n.a) { // TypeError: n is undefined
    console.log(n);
  }
}

go({a:[1,2,3]});

在循环中使用 let

在循环中使用 let 会有意想不到的效果,下面举一个例子,你可以自行测试看看。

html代码部分:

<h1>Buttons</h1>
<button>Button 0</button>
<button>Button 1</button>
<button>Button 2</button>
<button>Button 3</button>
<button>Button 4</button>
<button>Button 5</button>
<button>Button 6</button>
<button>Button 7</button>
<button>Button 8</button>
<button>Button 9</button>

然后 Javascript 部分:

const buttons = document.getElementsByTagName("button");

for(var i = 0; i < buttons.length; i++) {
  const button = buttons[i];
  button.addEventListener("click", function() {
      alert("Button " + i + " Pressed");
  });
}

这里我们在 for 循环里 对变量 i 的声明用的是 var,这里相当于全局变量,因此每次点击按钮的时候弹出的 i 的值都是 for 循环跑完后的全局变量 i 的值,但是如果我们改为用 let 来声明呢,把 i 变成块级变量,一切正常了,见下面的代码,请自行测试:

const buttons = document.getElementsByTagName("button");

for(let i = 0; i < buttons.length; i++) {
  const button = buttons[i];
  button.addEventListener("click", function() {
      alert("Button " + i + " Pressed");
  });
}

结语

还有更多地方需要注意和了解的可以查看下面的参考资料。

参考资料:

MDN Statements and declarations

MDN const

MDN let

ES2015 compatible table

You May Also Like

About the Author: ted

发表评论

电子邮件地址不会被公开。 必填项已用*标注