ES6随记

161 阅读4分钟

ES6随记(2019-12)

const iotVmsMainDriverIdArr = mainPersonnelList.filter(v => v.name === payload.mainDriver);
const iotVmsMainDriverId = iotVmsMainDriverIdArr.length === 1 ? iotVmsMainDriverIdArr[0]['iotVmsPersonnelId'] : '';

一、let 和 const 命令

let 特性:

  • 用来声明变量,只在它所在的代码块中有效,所以在此块级作用域中不可重复声明;
  • 不存在变量提升,声明后必须使用;
  • 块级作用域中未声明就是用会报错(暂时性死区);
// var 存在变量提升,undefined是一种数据类型
console.log(foo); // 输出undefined
var foo = 2;

// let 不声明就使用会报错
console.log(bar); // 报错ReferenceError
let bar = 2;

const 特性:

  • 具有上面 let 的三个特性;
  • 声明后所指向的内存地址不会变动: 声明的简单类型的数据(数值、字符串、布尔值)等同于常量,复合类型的数据(比如对象、数组)只保存指针,原数据的数据结构是不是可变的,不能控制;
const a = {value:1}
a.value = 2
console.log(a) //{value:2}

const b =[1,2,3]
b.push(4)
console.log(b) //[1,2,3,4]

ES6 声明变量的六种方法:

ES5只有两种:var命令和function命令。ES6添加了let和const命令,以及import命令和class命令。

二、解构赋值

ES6 允许按照一定的模式,从数组和对象中提取值,对变量进行赋值,这被称为解构(Destructuring)。
1.数组的解构

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

let [x, y, ...z] = ['a'];
x // "a"
y // undefined   解构不成功,变量的值就等于undefined。
z // []

2.对象的解构
解构对象时变量名与属性同名才能取到正确的值;

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

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

当然变量名与属性名不一致时,可以这样写:

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

let obj = { first: 'hello', last: 'world' };
let { first: f, last: l } = obj;
f // 'hello'
l // 'world'

对象的解构赋值的内部机制是先找到同名属性,然后在赋给对应的变量,所以,真正被赋值的是后者而不是前者。对象可以嵌套解构,可以指定默认值;其他类型也可以解构赋值,这里就不一一说明了。

3.解构赋值的部分使用场景
交换变量的值:

let x = 1;
let y = 2;

[x, y] = [y, x];

提取 JSON 数据:

let jsonData = {
  id: 42,
  status: "OK",
  data: [867, 5309]
};

let { id, status, data: number } = jsonData;

console.log(id, status, number);
// 42, "OK", [867, 5309]

遍历 Map 结构:

const map = new Map();
map.set('first', 'hello');
map.set('second', 'world');

for (let [key, value] of map) {
  console.log(key + " is " + value);
}
// first is hello
// second is world

// 获取键名
for (let [key] of map) {
  // ...
}

// 获取键值
for (let [,value] of map) {
  // ...
}

三、数据类型的扩展

1.字符串的扩展
字符串的扩展有很多,写一下我认为能用到的几点:
ES6为字符串添加了遍历器接口(详见《Iterator》),让字符串可以被for···of循环遍历。

for (let codePoint of 'foo') {
  console.log(codePoint)
}
// "f"
// "o"
// "o"

实例方法:includes(), startsWith(), endsWith()
传统上,JavaScript只有indexOf方法可以用来确定一个字符串是否包含在另一个字符串中。现在,ES6又提供了三种新的方法:

  • includes():返回布尔值,表示是否找到参数字符串。
  • startsWith():返回布尔值,表示参数字符串是否在原字符串的头部。
  • endsWith():返回布尔值,表示参数字符串是否在原字符串的尾部。

这三种方法都支持第二个参数,表示开始搜索的位置。

 let s = 'Hello world!';

s.startsWith('Hello') // true  ;表示参数字符串是否在原字符串的尾部
s.endsWith('!') // true ;表示参数字符串是否在原字符串的头部
s.includes('o') // true ;是否找到参数字符串

实例方法:repeat()
repeat 方法返回一个新字符串,表示将原字符串重复n次。参数如果是小数则取整,不能小于等于-1,-1(不包含)到1(不包含)视同为0,NAN也是一样,数字型的字符串会自动转换,不是则为“”;

'hello'.repeat(2) // "hellohello"

实例方法:padStart(),padEnd()
padStart()用于头部补全,padEnd()用于尾部补全。第一个参数是字符串补全生效的最大长度,第二个参数是用来补全的字符串。

'x'.padStart(5, 'ab') // 'ababx'
'x'.padStart(4) // '   x',第二个参数不填表示为空格

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

'12'.padStart(10, 'YYYY-MM-DD') // "YYYY-MM-12"
'09-12'.padStart(10, 'YYYY-MM-DD') // "YYYY-09-12" //用来提示字符串格式

实例方法:trimStart(),trimEnd()
trimStart()消除字符串头部的空格,trimEnd()消除尾部的空格。它们返回的都是新字符串,不会修改原始字符串。

const s = '  abc  ';

s.trim() // "abc"
s.trimStart() // "abc  "
s.trimEnd() // "  abc"

实例方法:matchAll()
matchAll()方法返回一个正则表达式在当前字符串的所有匹配,详见《正则的扩展》的一章。

还有一个很重要的扩展。模板字符串的写法:用反引号(`)标识。它可以当作普通字符串使用,也可以用来定义多行字符串,或者在字符串中嵌入变量,变量名卸载${}之中,或者也可以调用函数,也可以嵌套模板。

function authorize(user, action) {
  if (!user.hasPrivilege(action)) {
    throw new Error(
      // 传统写法为
      // 'User '
      // + user.name
      // + ' is not authorized to do '
      // + action
      // + '.'
      `User ${user.name} is not authorized to do ${action}.`);
  }
}

2.数值的扩展