js面试总结(4)— ES6新特性(更新中)

135 阅读3分钟

ES6 新特性总结

  1. let const
  2. 模板字符串
  3. 解构赋值
  4. 函数的参数默认值
  5. Spread/Rest操作符...
  6. 箭头函数
  7. for ... of
  8. class类
  9. 导入导出
  10. Promise
  11. async/await
  12. Symbol
  13. Set集合
  14. 对象的简化赋值
  15. Set和Map数据结构
  16. Proxy
  17. Reflect
  18. Module

1. let const

let命令

①let和var类似,但let声明的变量只在所在地代码块最有效

②for循环计数器,就很合适使用let命令

  • for循环10个代码块,每个代码块用独自的i
for (let i = 0; i < 10; i++) {
  // ...
}

console.log(i); // ReferenceError: i is not defined
  • for循环10个代码块,每个代码块共用一个i
for (var i = 0; i < 10; i++) {
  // ...
}

console.log(i); // 10

③不存在变量提升

  • var会发生变量提升,值为undefined,这种现象其实是多多少少有些奇怪的,按照一般的逻辑,变量应该在声明语句之后才可以使用
  • let为了纠正这种现象,let命令改变了语法行为
console.log(a); // undefined
var a = 1;

console.log(b); // ReferenceError: b is not defined
let b = 2;

④暂时性死区

  • 使用let声明的变量,当前块级区域内,无论外部的变量重名与否,都与这块级区域内的变量名无关
var tmp = 123;

if (true) {
  tmp = 'abc'; // ReferenceError
  let tmp;
}

⑤let不允许重复声明

let a = 1;
let a = 2; // 报错

⑥let变量的不会绑定在window对象上(及时是在最外层定义的也不刽),而var会

  • 这一点是ES6在把全局变量与顶层对象(window)的属性分割开来,之前的var是全局变量,而且会绑定在window顶层对象上,意思就是全局变量没有与顶层对象发的属性分割开来,会出现一些问题。

const命令

①const命令声明一个只读的常量,一旦声明,常量的值就不能改变 (重新赋值会报错)

②const命令声明的变量须在定义的时候就立即初始化,不能留到以后赋值(定义时不赋值会报错)

③const与let的作用域相同,只在声明所在的块级作用域有效

④const声明的常量也不进行变量提升,也存在暂时性死区

⑤const声明的常量与let一样不可以重复声明

⑥const定义的变量也不会绑定在window上,会于顶层对象window上的属性分割开来

const命令本质

  • const命令实际上保证的不是变量的值不能改动,而是所保存的地址不能改动(地址指向保存的那个变量),例如简单的数据类型(number,string,boolean),改变值就相当于改变了地址,所以不能改动,而复合数据类型(Object,Array),只要不改变整体的值,就不会改变其地址,所以对象或数组内存储的数据是可以改变的。

2. 模板字符串

  • 模板字符串是增强版的字符串,用反引号(`)标识。
  • 使用${ }的形式添加变量 用法:
var a = "张三", b = "李四"
console.log(`我是${a},你好${b}`);
// 等同于
console.log("我是" + a + ", 你好" + b)

3. 解构赋值

数组的解构

let [a, b, c] = [1, 2, 3]
let [a, [[b], c]] = [1, [[2],3]]
let [a, , b] = [1, 2, 3] // a =1, b =3
let [a = 1, b] = [] // a = 1, b = undefined
let [a, ...b] = [1, 2, 3] // a = 1, b = [2, 3]
let [a, b, c, d, e] = "hello" // a = 'h', b = 'e', ...
let [a = 2] = [undefined] // a = 2
let [a = 3, b = a] = [] // a = 3, b = 3
let [a = 3, b = a] = [1, 2] // a = 1, b = 2

对象的结构

let { a, b } = { a: 1, b: 2 } // a = 1, b = 2
let { a: data } = { a: 123 } // data = 123
let { p: [x, { y }] } = { p: ["hello", {y: "world"}] } // x = "hello", y = "world"
let { p: [{ y }, x] } = { p: [{ y: "world" }] } // x = undefined, y = "world"
let { a, b, ...rest } = { a: 10, b: 20, c: 30, d: 40 } // rest = { c: 30, d: 40 }
let { a = 10, b = 5 } = { a: 3 } // a = 3, b = 5
let { a: aa = 10, b: bb = 5 } = { a: 3} // aa = 3, bb = 5

4. 函数的参数默认值

  • ES6之前,在传参时,不能给参数设定默认值,在ES6中,函数传参时可以设置默认值
function foo(a = 1, b = 2){
    console.log(a + b); // 3
}

foo() // 3

5. Spread / Rest 操作符 ...

Spread操作符

  • 当...用于函数调用,传递实参,或类似的表达式中,它就是Spread操作符,它会把一个数组展开为逗号分割的元素列表
function foo(x, y, z){
    console.log(x, y, z)
}

let arr = [1, 2, 3]
foo(...arr) // 1 2 3
  • 当...用于函数的参数列表时,及用于形参的表示时,它就是Rest操作符,它会把...对应的实参收集到一个数组当中
function foo(...args){
    console.log(args)
}

foo(1, 2, 3, 4, 5) // [1, 2, 3, 4, 5]

6. 箭头函数

箭头函数出现的目的

  • 箭头函数出现的目的是为了解决this指向问题

箭头函数的特性

  • 箭头函数使用" => "定义
  • 箭头函数比function定义的函数更简洁,有一些简便写法
  • 箭头函数本身没有绑定this,其内的this指向在定义时就确定了(指向定义时所在对象或者可以理解为指向临近的外层作用用)
  • 因为箭头函数本身没有绑定this,所以不能用作构造函数
const foo = (a) => console.log(a)

foo(3) // 3

7. for ... of

for ... in

  • for ... in:遍历对象的属性,及key

for ... of

  • for ... of:遍历对象的属性的值,及value

8. class类

ES6的class类实际上可以看成是一个原型链的语法糖

  • class的绝大部分功能,使用ES5的原型链及原型对象都可以实现
function Point(x, y){
    this.x = x;
    this.y = y;
}

Point.prototype.toString = function (){
    return `(${this.x}, ${this.y})`
}

var p = new Point(1, 2)
console.log(p.toString()) // (1, 2)

等同于:

class Point {
    constructor(x, y){
        this.x = x;
        this.y = y;
    }
    
    toString(){
        return `(${this.x}, ${this.y})`
    }
}

var p = new Point(1, 2);
console.log(p.toString())

类的继承

class Point{
}

class ColorPoint extends Point{
}

9. 导入导出

导入

  • import ES6新规范
  • required CommonJs的语法(CommonJs用于node)

导出

  • export ES6新规范,直接通过export导出变量或内容
  • exports CommonJS的语法,通过module.exports导出模块中的内容

10. Promise

Promise出现的目的

  • 解决异步编程的一种方法,及解决回调地狱的问题(回调地狱问题就是,在请求到的成功回调函数里继续写函数,形成了回调地狱,层级多时代码可读性低,不好维护)
  • 于是乎,Promise就出现了,通过.then()的方法来写成功后的回调函数,然后若再想操作,再写.then(),以此类推