ES6 基础回顾

企业项目实战 > 第一部分 > ES6 代码规范与基础回顾

ES6 基础回顾

什么是 ES6

ES6, 全称 ECMAScript 6.0, 是 JavaScript 的一个版本标准, 真正的 ES6 仅指 ECMAScript2015, 但实际上在目前的大多的网络文章中, ES6 泛指自 ECMA2015 到最新的 ECMAScript2020 中的所有新增标准及这些标准提供的一些新方法实现。

为什么要使用 ES6

ES5 已经不能满足目前前端越来越复杂、庞大的现状, 甚至我们可以说它已经过时了。而 ES6 是对 ES5 的增强和升级, 增加了很多新标准和支持新标准的方法。当前主流的浏览器都已经全面支持 ES6 且行业内大多数前端框架都已经全面使用 ES6 标准来实现。一些非传统前端产品如微信小程序、uni-app 等都是基于 ES6 的语法。我们学习使用 ES6 是因为 ES6 提供了更多更方便更实用且更有效率的方法, 避免了每个人因为自己的习惯去开发不同的工具包。

ES6 的关键特性

const & let

  • const 常量声明

用于定义常量, 什么时候声明常量?声明该变量所在的作用域内永远不会被重新赋值的变量, 必须使用 const 定义。

  • let 变量声明

用于定义变量, 什么时候声明变量?声明该变量所在的作用域内有重新为变量赋值的可能, 可以使用 let 定义。

  • 什么是变量提升

JavaScript 代码的执行分为两个阶段:
第一个阶段会将当前文件预读一遍, 同时在当前执行环境中注册所有的变量声明和函数声明, 可以理解为都解析了一遍。但要注意的是, 这里注册的仅仅只是声明, 赋值操作仍在原有的位置上;
第二个阶段会从上到下依次执行代码, 如果是赋值就给变量赋值, 如果是方法就执行方法, 方法中遇到了变量就回去内存中查找, 如果变量已赋值, 则返回值, 如果未赋值则返回 undefined;
注意:虽然 const 与 let 也会被预处理, 但没有变量提升, 在哪定义就在哪里使用;
变量声明会被提升到其当前作用域的最上面而不是整个程序的最上面;
变量提升的优先级:函数声明 > 变量声明 > 参数赋值。

var a = 1;
function test() {
  console.log(a, 'a1'); // undefined
  var a = 2; // a被预读后存在了内存里, 当函数被调用时, a变量已存在, 所以a1位置时可以读取到变量
  console.log(a, 'a2'); // 2, a已经被赋值
  function test1(a) {
    console.log(a, 'a3'); // 5, 接收到的参数为提升上来的a赋值
    var a = 3; // a被预读后提升至当前作用域的最上方
    a = 4;
    console.log(a, 'a4'); // 4
  }
  // 指定时间后执行传入的参数方法, 该参数方法是一个用后即销毁的闭包, 内部环境中如有使用外部变量的, 以调用时为准
  setTimeout(function () {
    console.log(a, 'a5'); // 7
    test1(a);
  }, 500);
  var a = 5;
  test1(a);
  setTimeout(
    function (a) {
      console.log(a, 'a6'); // 6
    },
    0,
    6
  );
  var a = 7;
}
test();
  • 什么是暂时性死区

暂时性死区这个概念仅存在于 let 与 const 命令。ES6 明确规定, 如果在当前作用域中存在以 let 或 const 命令声明的变量, 那么, 在声明它之前, 这个变量都是不可用的。
暂时性死区概念主要是为了解决变量提升问题, 防止在变量声明前就使用这个变量, 从而导致意外的行为与操作。

a = 2; // 这里是死区, 初始化之前不能使用a。
console.log(a);
let a;

模板字符串

为什么要使用模板字符串而不是使用“+”运算符来拼接字符串?字符串拼接是所有程序设计语言都需要的操作。当拼接结果较长时, 如何保证效率就成为一个很重要的问题。早些年的时候在阅读《javascript 高级程序设计》中, 有一段关于字符串特点的描述记得很深刻。原文应该是这样说的:ECMAScript 中的字符串是不可变的, 也就是说, 字符串一旦创建, 他们的值就不能改变。要改变某个变量的保存的的字符串, 首先要销毁原来的字符串, 然后再用另外一个包含新值的字符串填充该变量。

let lang = 'java';
lang = lang + 'Script';

上面这段代码看起来很简单, 但实际上操作稍有些复杂, 解析器首先会创建一个新字符串, 然后在这个字符串中填充“Java”和“Script”, 然后销毁原来的字符串“Java”和“Script”, 因为这两个字符串已经没用了。
所以, 在早期没有模板字符串以前, 我们进行一些较复杂字符串拼接都是使用的数组 push, 然后再使用 join 方法来进行拼接。这种方式的好处是因为数组本身是一个引用类型, 所有的成员都只占用其本身所占用的资源, 直到被 join 方法调用时, 才会一次展开后以指定的符号连接成一个新的字符串, 它们不存在多次建立和销毁这种情况。
而模板字符串则是换了个方式, 它生成了一串完整的字符串, 在这个字符串中去查询所有以’${‘开头, 以’}'结尾的代码片段, 匹配到后将内部的表达式进行运算取值后重新填充回原处。在字符串比较短时这种作法可能没有多大优势, 但在对长字符串做处理时就会大大优化处理速度与内存的占用率。

对象和数组解构

参考代码规范的解构部分 ./lessons_01.md

数组的遍历 for…of

在可以使用它来实现遍历的情况下, 我们建议不要使用 for 循环, 在小型的数据遍历场景中, 它的效率及资源占用相对于其它的遍历来说是最少的; 当然,对于超大型的遍历来说, 还是 for 循环比较好用。只是一般情况下,我们极少会接触到超大型的遍历,所以,为了保持代码的一致性,我们更希望使用 for…of。
在已知数组长度的情况下, 不要使用 forEach, forEach 是用于处理未知长度的数组的, 它的效率及资源占用相对都是非常高的。

你可能感兴趣的:(es6,基础回顾,js,javascript,es6)