ES6系列

144 阅读6分钟

let和const

let

  • 块级作用域 let声明的变量只在它所在的代码块有效;
  • 不存在变量提升;
// var 的情况
console.log(foo); // 输出undefined
var foo = 2;

// let 的情况
console.log(bar); // 报错ReferenceError
let bar = 2;

  • 在代码块内,使用let命令声明变量之前,该变量都是不可用的。这在语法上,称为“暂时性死区”;
if (true) {
  // TDZ开始
  tmp = 'abc'; // ReferenceError
  console.log(tmp); // ReferenceError

  let tmp; // TDZ结束
  console.log(tmp); // undefined

  tmp = 123;
  console.log(tmp); // 123
}

  • 不允许重复声明; let不允许在相同作用域内,重复声明同一个变量。

const

  • const声明一个只读的常量,const一旦声明变量,就必须立即初始化;
let count;   // 不会报错
const count;  //SyntaxError: Missing initializer in const declaration
const count = 30;  // 正确声明
  • const声明的变量不能再赋值;如果变量是引用类型,可以修改对象的属性值,但不可以重新修改绑定的对象。
const count = 20;
count = 30;  // TypeError: Assignment to constant variable.

const obj = {};
obj.name = 'jackson';

本质: const变量不能修改指针,但是可以修改值.

let、const与var的区别

  • 块级作用域,不存在变量提升;
  • 不允许重复定义;
  • 声明前不允许使用变量,存在暂时性死区;
  • for循环中每次创建新的副本:let声明的变量则只在循环体内有效;
  • 全局声明不作为 window 属性:利用 var 在全局声明变量,会作为window对象的一个属性存在,而let 和const则不会。

模板字符串

用反撇号代 ` 替单引号或者双引号:

const message = `template+`;
console.log(message);

字符串占位符

${js表达式}

const name = 'hh';
const msg = `Hello, I am ${name}`; // Hello, I am hh

变量解构赋值(常用)

对象

对象的解构赋值的内部机制,是先找到同名属性,然后再赋给对应的变量。

let { foo, bar } = { foo: 'aaa', bar: 'bbb' };
foo // "aaa"
bar // "bbb"

数组

let [head, ...tail] = [1, 2, 3, 4];
head // 1
tail // [2, 3, 4]

字符串新增方法

includes(), startsWith(), endsWith()

传统上,JavaScript 只有indexOf方法,可以用来确定一个字符串是否包含在另一个字符串中。ES6 又提供了三种新方法。

  • includes():返回布尔值,表示是否找到了参数字符串。
  • startsWith():返回布尔值,表示参数字符串是否在原字符串的头部。
  • endsWith():返回布尔值,表示参数字符串是否在原字符串的尾部。
let s = 'Hello world!';

s.startsWith('Hello') // true
s.endsWith('!') // true
s.includes('o') // true

padStart(),padEnd()

字符串补全长度的功能。如果某个字符串不够指定长度,会在头部或尾部补全。padStart()用于头部补全,padEnd()用于尾部补全。

'x'.padStart(5, 'ab') // 'ababx'
'x'.padStart(4, 'ab') // 'abax'

'x'.padEnd(5, 'ab') // 'xabab'
'x'.padEnd(4, 'ab') // 'xaba'

padStart()和padEnd()一共接受两个参数,第一个参数是字符串补全生效的最大长度,第二个参数是用来补全的字符串。

函数扩展

常用的有参数默认值,不定参数,展开运算符和箭头函数等。

参数默认值

在es5函数的默认值是用||实现;在es6中,可以直接在参数列表直接用=赋值方式定义默认值:

function func(url, timeout = 2000, cb = function() {}) {
  console.log(url, timeout, cb);
}

rest参数

ES6 引入 rest 参数(形式为...变量名),用于获取函数的多余参数。 arguments对象不是数组,而是一个类似数组的对象。所以为了使用数组的方法,必须使用Array.prototype.slice.call先将其转为数组。 rest 参数是一个数组,数组特有的方法都可以使用。

// arguments变量的写法
function sortNumbers() {
  return Array.prototype.slice.call(arguments).sort();
}

// rest参数的写法
const sortNumbers = (...numbers) => numbers.sort();

展开运算符

展开运算符用...符号表示

const arr = [1, 2, 3]
let arr2=[44, ...arr]
console.log(arr2)//[44, 1, 2, 3]

箭头函数

箭头函数只是当作是普通函数一种简写方式。特点如下:

(1)没有this绑定:在箭头函数中无this对象;

(2)函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象。

(3)不能作为new调用:不可以当作构造函数,也就是说,不可以使用new命令,否则会抛出一个错误。

(4)没有arguments参数:不可以使用arguments对象,该对象在函数体内不存在。如果要用,可以用 rest 参数代替。

数组扩展

扩展运算符...

展开数组,将一个数组转为用逗号分隔的参数序列。

1、展开数组
console.log(...[1, 2, 3])
// 1 2 3

2、复制数组
let colors = ['red', 'green', 'blue'];
let [...cloneColors] = colors;  // es6
let cloneColors=[...colors] //es6

3、合并数组
const arr1 = ['a', 'b'];
const arr2 = ['c'];
const arr3 = ['d', 'e'];

// ES5 的合并数组
arr1.concat(arr2, arr3);
// [ 'a', 'b', 'c', 'd', 'e' ]

// ES6 的合并数组
[...arr1, ...arr2, ...arr3]
// [ 'a', 'b', 'c', 'd', 'e' ]

4、将字符串转为真正的数组
[...'hello']
// [ "h", "e", "l", "l", "o" ]

Array.from()

将类对象转换为数组;将字符串转为数组,然后返回字符串的长度。

let arrayLike = {
    '0': 'a',
    '1': 'b',
    '2': 'c',
    length: 3
};

// ES5的写法
var arr1 = [].slice.call(arrayLike); // ['a', 'b', 'c']

// ES6的写法
let arr2 = Array.from(arrayLike); // ['a', 'b', 'c']

array.of()

Array.of()方法用于将一组值,转换为数组。

Array.of(3, 11, 8) // [3,11,8]
Array.of(3) // [3]
Array.of(3).length // 1

对象扩展

字面量语法扩展

当对象属性名和变量名相同时,赋值的时候可以省略变量名

function getObj(name, age) {
  return {
    name,
    age
  }
}

对象的扩展运算符(...)

用于取出参数对象的所有可遍历属性,拷贝到当前对象之中。等同于使用Object.assign()方法;

let z = { a: 3, b: 4 };
let n = { ...z };
n // { a: 3, b: 4 }

let aClone = { ...z };
// 等同于
let aClone = Object.assign({}, z);

新增对象方法

1、利用 Object.is 判断两个值是否全相等:

console.log(Object.is(5, '5')); // false
console.log(Object.is(5, 5));  // true

2、利用 Object.assign 合并对象

Symbol对象

表示独一无二的值。调用全局函数 Symbol 创建,该函数接收一个字符串作为描述参数。

let s1 = Symbol('foo');
let s2 = Symbol('bar');

s1 // Symbol(foo)
s2 // Symbol(bar)
  • 用途
  • 作为对象的属性和方法,模拟对象的私有属性;
let mySymbol = Symbol();

// 第一种写法
let a = {};
a[mySymbol] = 'Hello!';

// 第二种写法
let a = {
  [mySymbol]: 'Hello!'
};
  • 定义常量,防止常量重复定义:
const COLOR_RED = Symbol('red');
const COLOR_BLUR = Symbol('blue');

switch (color) {
  case COLOR_RED:
    break;
  case COLOR_BLUR:
    break;
  //
}

Set 和 Map

  • Set Set本身是一个构造函数,用来生成 Set 数据结构。
const s = new Set();
[2, 3, 5, 4, 5, 2, 2].forEach(x => s.add(x));
for (let i of s) {
  console.log(i);
}
// 2 3 5 4

去重

1、利用Set 进行数组去重
[...new Set(array)]
2、去除字符串里面的重复字符
[...new Set('ababbc')].join('')
// "abc"

Proxy

用 new Proxy(target, handler) 新建一个代理对象,target 表示代理的目标对象,handler 是一个拦截行为的配置对象。

var proxy = new Proxy(target, handler);

let obj = {
  name: 'hhh'
};

let proxy = new Proxy(obj, {});

console.log(proxy.name);
proxy.name = 'aaa';
console.log(obj.name);

Promise对象

用new Promise() 创建一个 Promise 对象:

let p = new Promise((resolve, reject) => {
   if (/* 异步操作成功 */){
    resolve(value);
  } else {
    reject(error);
  }
})

Promise 对象有3种状态:

  • pending: 表示进行中的状态
  • fulfilled: 任务完成的状态,调用resolve()后触发
  • rejected: 任务失败的状态, 调用reject()后触发

async函数

async函数返回一个 Promise 对象,可以使用then方法添加回调函数。

错误处理

1、在try...catch 中捕获;

async function f() {
  try {
    await Promise.reject('出错了');
  } catch(e) {
  }
  return await Promise.resolve('hello world');
}

f().then(v => console.log(v))
// hello world

2、在 await 后面的 Promise 对象的后面再跟上一个 catch() 方法;

async function f() {
  await Promise.reject('出错了').catch(e => console.log(e));
  return await Promise.resolve('hello world');
}

f().then(v => console.log(v))
// 出错了
// hello world

参考: es6.ruanyifeng.com/#docs/promi…

juejin.cn/post/684490…