ES6 新特性

140 阅读6分钟

1.1 let 和 const

for (var i = 0; i < 5; i++) {
    console.log(i)
}
// 作用域不可控
console.log("循环外: " + i);

// 1. let
for (let j = 0; j < 5; j++) {
  console.log(j)
}
// j is not defined
// console.log("循环外: " + j);

// 2. const
const str = "abc";
console.log(str);
str = "123";
// Assignment to constant variable.
console.log(str);

1.2 字符串扩展

  • includes(): 返回布尔值,表示是否找到了参数字符串
  • startsWith(): 返回布尔值,表示参数字符串是否在原字符串头部
  • endsWith(): 返回布尔值,表示参数字符串是否在原字符串尾部
let str = "hello echo";
// 1. includes
console.log(str, "中是否包含了 echo", str.includes("echo"));
console.log(str, "中是否包含了 echo2", str.includes("echo2"));

// 2. startsWith
console.log(str, "中是否以hello 开头", str.startsWith("hello"));
console.log(str, "中是否以hello2 开头", str.startsWith("hello2"));

// 3. endsWith
console.log(str, "中是否以echo 结尾", str.endsWith("echo"));
console.log(str, "中是否以echo2 结尾", str.endsWith("echo2"));

// 字符串模板 (按原格式输出)
let str2 = `
hello,
my name is
echo
`;
console.log(str2);

1.3 解构表达式

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

// 1. 数组的解构
let arr = [1, 2, 3];
console.log(arr[1]);

let [x, y, z] = arr;
console.log(x);
console.log(y);
console.log(z);
// 拿到第一个值
let [x1] = arr;
console.log(x1);

// 2. 对象的解构
const person = {
    name: 'echo',
    age: 22,
    language: ['java', 'js', 'css']
};
// 对象中的属性名称
let {name, age, language} = person;
console.log(name, age, language);

// 对象中的属性重命名
let {name: n, age: a, language: l} = person;
console.log(n, a, l);

1.4 函数 默认值

function add(a, b) {
  // if (!b) {
  //   b = 1;
  // }
  // 设置默认值
  b = b || 1;
  return a + b;
}

// ES6函数设置默认值
function add2(a, b = 1) {
  return a + b;
}

console.log(add(10));

console.log(add2(10));
console.log(add2(10, 2))

1.5 箭头函数

// 普通函数
function print(a) {
  console.log(a);
}
print("123");

// 箭头函数
// 1. 单个参数
let print2 = a => console.log(a);
print2("456");

// 2. 多个参数
let sum = (a, b) => console.log(a + b);
sum(10, 15);

let sum2 = (a, b) => {
// 先 a + b, 再 return
  return a + b;
};

console.log(sum2(10, 3));

// 3. 无参数
let sayHello = () => console.log("hello");
sayHello();

1.6 函数属性缩写

let person = {
  name: 'echo',
  // 1. 传统写法
  eat: function (food) {
    console.log(this.name + "在吃:" + food);
  },
  // 2. 箭头函数写法
  eat2: food => console.log(person.name + "在吃:" + food),
  // 3. 直接写函数
  eat3 (food) {
    console.log(this.name + "在吃:" + food);
  }
};

person.eat("冬瓜");
person.eat2("西瓜");
person.eat3("南瓜");

// 箭头函数和解构赋值共用
const person2 = {
  name: 'echo2',
  age: 22,
  language: ['java', 'js', 'css']
};

function hello(person) {
  console.log("hello, " + person.name);
}

hello(person2);

// 箭头函数 + 解构赋值
let hello2 = ({name}) => console.log("hello, " + name);
hello2(person2);

1.7 map 和 reduce方法

  • map(): 接收一个函数,将原数组中的所有元素用这个函数处理后放入新的数组返回。
  • reduce(): 接收一个函数(必须)和一个初始值(可选),该函数接收两个参数
    • 第一个参数是上一个reduce处理的结果
    • 第二个参数是数组中要处理的下一个元素
  • reduce() 会从左到右依次把数组中的元素用reduce处理, 并把处理的结果作为下次reduce的第一个参数, 如果是第一次, 会把前两个元素作为计算参数,或者把用户指定的初始值作为起始参数。
// 1. map
let arr = ['1', '20', '-5', '3'];
console.log(arr);

// 使用箭头函数
let arr2 = arr.map(s => parseInt(s));
console.log(arr2);

// 使用传统方式
let arr3 = arr.map(function (s) {
  return parseInt(s);
});
console.log(arr3);

// 2. reduce
const arr4 = [1, 20, -5, 3];

let sum = arr4.reduce((a, b) => {
  return a + b;
});
console.log(sum);

let sum2 = arr4.reduce((a, b) => {
  return a + b;
}, 1); // 第二个参数为初始值
console.log(sum2);

1.8 扩展运算符

扩展运算符是三个点(...), 将一个数组转为用逗号分隔的参数序列。

console.log([1, 2, 3]);
console.log(...[1, 2, 3]);

console.log(0, ...[1, 2, 3], 4, 5);

// 1. 数组展开
function add(x, y) {
  return x + y;
}
let nums = [1, 2];
console.log(add(...nums));

// 2. 数组合并
let arr = [...[1, 2, 3], ...[4, 5, 6]];
console.log(arr);

// 3. 与解构表达式结合
const [first, ...rest] = [1, 2, 3, 4, 5];
console.log(first, rest);

// 4. 将字符串转成数组
console.log([...'hello']);

1.9 Promise

const p = new Promise((resolve, reject) => {
  // 写异步操作,通常ajax的操作
  setTimeout(() => {
      // 异步操作 (模拟)
      let num = Math.random();
      if (num < 0.5) {
        // 认为成功了
        resolve("成功了 " + num);
      } else {
        // 认为失败了
        reject("失败了 " + num);
      }
  });
});

console.log("ok");

p.then(value => {
  console.log(value);
}).catch(reason => {
  console.log(reason);
});

console.log("ok2");

2.0 Set 和 Map

Set: 本质与数组类似,不同在于Set中只能保存不同元素,如果元素相同会被忽略,和Java中的Set集合非常相似。 Map: 本质与Object类似的结构,不同在于Object强制规定key只能是字符串,而Map结构的key可以是任意对象。 - object是<string, object> 集合 - map是<object, object> 集合

// 1. set
let set = new Set();
set.add(1);
set.add(2);
console.log(set);
// 接收数组
let set2 = new Set([2, 3, 4, 5, 5]);
console.log(set2);

// set 遍历
set2.forEach(value => {
  console.log(value);
});

// 2. map
const map = new Map([
  ['key1', 'value1'],
  ['key2', 'value2'],
]);

map.set("key3", "value3");
console.log(map.get("key3"));

map.forEach(((value, key) => {
  console.log(key, value);
}));

console.log(...map.values());

2.1 Class类的基本语法

// 1. 类的定义
class User {
    // 构造函数
    constructor(name, age = 20) {
      this.name = name;
      this.age = age;
    }
    sayHello() {
      return "hello, " + this.name;
    }
    // 静态函数
    static isAdult(age) {
      if (age > 18) {
        return "成年人";
      }
      return "未成年人";
    }
}

let user = new User("echo", 18);
console.log(user);
console.log(user.sayHello());
// 静态方法的使用
console.log(User.isAdult(17));

// 2. 类的继承
class Lisi extends User {
    constructor() {
      super("蔡徐坤", 22);
    }
    test() {
      return "test ->" + this.name;
    }
}

let lisi = new Lisi();
console.log(lisi);
console.log(lisi.test());
console.log(lisi.sayHello());
console.log(Lisi.isAdult(18));

2.2 Generator函数

Generator函数是ES6提供的一种异步编程解决方案,语法行为与传统函数完全不同。 Generator函数有两个特征:一是function命令与函数名之间有一个星号,二是函数体内部使用yield关键字定义不同的内部状态。

// Generator
function* hello() {
    yield "hello";
    yield "world";
    yield "echo";
    yield "yu";
}

let h = hello();
console.log(h);
// console.log(h.next());
// console.log(h.next());
// console.log(h.next());
// console.log(h.next());
// console.log(h.next());

// 遍历获取值
for (let v of h) {
  console.log(v);
}

2.3 修饰器

修饰器(Decorator) 是一个函数,用来修改类的行为。ES2017引入了这项功能,目前Babel转码器已经支持。

@T
class User {
    constructor(name, age = 20) {
      this.name = name;
      this.age = age;
    }
}

function T(target) { // target: 被修饰的对象
    console.log(target);
    target.contry = "中国"; // 通过修饰器添加的属性是静态属性
}

console.log(User.contry);

2.4 转码器 UmiJS

## 安装tyarn 淘宝的yarn镜像
npm i yarn tyarn -g

## 测试tyarn是否安装成功
tyarn -v

## 使用tyarn 全局安装umi
tyarn global add umi

## 测试umi 安装情况
umi

## 遇到问题: umi 不是内部或外部命令 也不是可运行的程序
yarn golbal bin

C:\Users\eyu7\AppData\Local\Yarn\bin\umi generate page index
## 复制上面的global bin的路径, 添加到系统环境变量PATH

## 如果仍然不行, 全路径启动
C:\Users\eyu7\AppData\Local\Yarn\bin\umi generate page index

C:\Users\eyu7\AppData\Local\Yarn\bin\umi dev

2.5 模块化

什么是模块化: 模块化就是把代码进行拆分,方便重复利用。

模块功能主要由两个命令

  • export
  • import
class Util {
  static sum = (a, b) => {
    return a + b;
  }
}

export default Util;
import Util from "./Util";

@T
class User {
  constructor(name, age = 20) {
    this.name = name;
    this.age = age;
  }
}

function T(target) { // target: 被修饰的对象
  // console.log(target);
  target.contry = "中国"; // 通过修饰器添加的属性是静态属性
}

console.log(User.contry);

console.log(Util.sum(10, 5));