博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
ES6 完全使用手册
阅读量:4972 次
发布时间:2019-06-12

本文共 14392 字,大约阅读时间需要 47 分钟。

前言

  1. 这里的 "ES6" 泛指 ES5 之后的新语法
  2. 这里的 "完全" 是指本文会不断更新
  3. 这里的 "使用" 是指本文会展示很多 ES6 的使用场景
  4. 这里的 "手册" 是指你可以参照本文将项目更多的重构为 ES6 语法

此外还要注意这里不一定就是正式进入规范的语法。

1. let 和 const

在我们开发的时候,可能认为应该默认使用 let 而不是 var,这种情况下,对于需要写保护的变量要使用 const。

然而另一种做法日益普及:默认使用 const,只有当确实需要改变变量的值的时候才使用 let。这是因为大部分的变量的值在初始化后不应再改变,而预料之外的变量的修改是很多 bug 的源头。

// 例子 1-1// badvar foo = 'bar';// goodlet foo = 'bar';// betterconst foo = 'bar';

2. 模板字符串

1. 模板字符串

需要拼接字符串的时候尽量改成使用模板字符串:

// 例子 2-1// badconst foo = 'this is a' + example;// goodconst foo = `this is a ${example}`;

2. 标签模板

可以借助标签模板优化书写方式:

// 例子 2-2let url = oneLine `    www.taobao.com/example/index.html    ?foo=${foo}    &bar=${bar}`;console.log(url); // www.taobao.com/example/index.html?foo=foo&bar=bar

oneLine 的源码可以参考

3. 箭头函数

优先使用箭头函数,不过以下几种情况避免使用:

1. 使用箭头函数定义对象的方法

// 例子 3-1// badlet foo = {  value: 1,  getValue: () => console.log(this.value)}foo.getValue();  // undefined

2. 定义原型方法

// 例子 3-2// badfunction Foo() {  this.value = 1}Foo.prototype.getValue = () => console.log(this.value)let foo = new Foo()foo.getValue();  // undefined

3. 作为事件的回调函数

// 例子 3-3// badconst button = document.getElementById('myButton');button.addEventListener('click', () => {    console.log(this === window); // => true    this.innerHTML = 'Clicked button';});

4. Symbol

1. 唯一值

// 例子 4-1// bad// 1. 创建的属性会被 for-in 或 Object.keys() 枚举出来// 2. 一些库可能在将来会使用同样的方式,这会与你的代码发生冲突if (element.isMoving) {  smoothAnimations(element);}element.isMoving = true;// goodif (element.__$jorendorff_animation_library$PLEASE_DO_NOT_USE_THIS_PROPERTY$isMoving__) {  smoothAnimations(element);}element.__$jorendorff_animation_library$PLEASE_DO_NOT_USE_THIS_PROPERTY$isMoving__ = true;// bettervar isMoving = Symbol("isMoving");...if (element[isMoving]) {  smoothAnimations(element);}element[isMoving] = true;

2. 魔术字符串

魔术字符串指的是在代码之中多次出现、与代码形成强耦合的某一个具体的字符串或者数值。

魔术字符串不利于修改和维护,风格良好的代码,应该尽量消除魔术字符串,改由含义清晰的变量代替。

// 例子 4-1// badconst TYPE_AUDIO = 'AUDIO'const TYPE_VIDEO = 'VIDEO'const TYPE_IMAGE = 'IMAGE'// goodconst TYPE_AUDIO = Symbol()const TYPE_VIDEO = Symbol()const TYPE_IMAGE = Symbol()function handleFileResource(resource) {  switch(resource.type) {    case TYPE_AUDIO:      playAudio(resource)      break    case TYPE_VIDEO:      playVideo(resource)      break    case TYPE_IMAGE:      previewImage(resource)      break    default:      throw new Error('Unknown type of resource')  }}

3. 私有变量

Symbol 也可以用于私有变量的实现。

// 例子 4-3const Example = (function() {    var _private = Symbol('private');    class Example {        constructor() {          this[_private] = 'private';        }        getName() {          return this[_private];        }    }    return Example;})();var ex = new Example();console.log(ex.getName()); // privateconsole.log(ex.name); // undefined

5. Set 和 Map

1. 数组去重

// 例子 5-1[...new Set(array)]

2. 条件语句的优化

// 例子 5-2// 根据颜色找出对应的水果// badfunction test(color) {  switch (color) {    case 'red':      return ['apple', 'strawberry'];    case 'yellow':      return ['banana', 'pineapple'];    case 'purple':      return ['grape', 'plum'];    default:      return [];  }}test('yellow'); // ['banana', 'pineapple']
// goodconst fruitColor = {  red: ['apple', 'strawberry'],  yellow: ['banana', 'pineapple'],  purple: ['grape', 'plum']};function test(color) {  return fruitColor[color] || [];}
// betterconst fruitColor = new Map()  .set('red', ['apple', 'strawberry'])  .set('yellow', ['banana', 'pineapple'])  .set('purple', ['grape', 'plum']);function test(color) {  return fruitColor.get(color) || [];}

6. for of

1. 遍历范围

for...of 循环可以使用的范围包括:

  1. 数组
  2. Set
  3. Map
  4. 类数组对象,如 arguments 对象、DOM NodeList 对象
  5. Generator 对象
  6. 字符串

2. 优势

ES2015 引入了 for..of 循环,它结合了 forEach 的简洁性和中断循环的能力:

// 例子 6-1for (const v of ['a', 'b', 'c']) {  console.log(v);}// a b cfor (const [i, v] of ['a', 'b', 'c'].entries()) {  console.log(i, v);}// 0 "a"// 1 "b"// 2 "c"

3. 遍历 Map

// 例子 6-2let map = new Map(arr);// 遍历 key 值for (let key of map.keys()) {  console.log(key);}// 遍历 value 值for (let value of map.values()) {  console.log(value);}// 遍历 key 和 value 值(一)for (let item of map.entries()) {  console.log(item[0], item[1]);}// 遍历 key 和 value 值(二)for (let [key, value] of data) {  console.log(key)}

7. Promise

1. 基本示例

// 例子 7-1// badrequest(url, function(err, res, body) {    if (err) handleError(err);    fs.writeFile('1.txt', body, function(err) {        request(url2, function(err, res, body) {            if (err) handleError(err)        })    })});// goodrequest(url).then(function(result) {    return writeFileAsynv('1.txt', result)}).then(function(result) {    return request(url2)}).catch(function(e){    handleError(e)});

2. finally

// 例子 7-2fetch('file.json').then(data => data.json()).catch(error => console.error(error)).finally(() => console.log('finished'));

8. Async

1. 代码更加简洁

// 例子 8-1// goodfunction fetch() {  return (    fetchData()    .then(() => {      return "done"    });  )}// betterasync function fetch() {  await fetchData()  return "done"};
// 例子 8-2// goodfunction fetch() {  return fetchData()  .then(data => {    if (data.moreData) {        return fetchAnotherData(data)        .then(moreData => {          return moreData        })    } else {      return data    }  });}// betterasync function fetch() {  const data = await fetchData()  if (data.moreData) {    const moreData = await fetchAnotherData(data);    return moreData  } else {    return data  }};
// 例子 8-3// goodfunction fetch() {  return (    fetchData()    .then(value1 => {      return fetchMoreData(value1)    })    .then(value2 => {      return fetchMoreData2(value2)    })  )}// betterasync function fetch() {  const value1 = await fetchData()  const value2 = await fetchMoreData(value1)  return fetchMoreData2(value2)};

2. 错误处理

// 例子 8-4// goodfunction fetch() {  try {    fetchData()      .then(result => {        const data = JSON.parse(result)      })      .catch((err) => {        console.log(err)      })  } catch (err) {    console.log(err)  }}// betterasync function fetch() {  try {    const data = JSON.parse(await fetchData())  } catch (err) {    console.log(err)  }};

3. "async 地狱"

// 例子 8-5// bad(async () => {  const getList = await getList();  const getAnotherList = await getAnotherList();})();// good(async () => {  const listPromise = getList();  const anotherListPromise = getAnotherList();  await listPromise;  await anotherListPromise;})();// good(async () => {  Promise.all([getList(), getAnotherList()]).then(...);})();

9. Class

构造函数尽可能使用 Class 的形式

// 例子 9-1class Foo {  static bar () {    this.baz();  }  static baz () {    console.log('hello');  }  baz () {    console.log('world');  }}Foo.bar(); // hello
// 例子 9-2class Shape {  constructor(width, height) {    this._width = width;    this._height = height;  }  get area() {    return this._width * this._height;  }}const square = new Shape(10, 10);console.log(square.area);    // 100console.log(square._width);  // 10

10.Decorator

1. log

// 例子 10-1class Math {  @log  add(a, b) {    return a + b;  }}

log 的实现可以参考

2. autobind

// 例子 10-2class Toggle extends React.Component {  @autobind  handleClick() {    console.log(this)  }  render() {    return (      <button onClick={this.handleClick}>        button      </button>    );  }}

autobind 的实现可以参考

3. debounce

// 例子 10-3class Toggle extends React.Component {  @debounce(500, true)  handleClick() {    console.log('toggle')  }  render() {    return (      <button onClick={this.handleClick}>        button      </button>    );  }}

debounce 的实现可以参考

4. React 与 Redux

// 例子 10-4// goodclass MyReactComponent extends React.Component {}export default connect(mapStateToProps, mapDispatchToProps)(MyReactComponent);// better@connect(mapStateToProps, mapDispatchToProps)export default class MyReactComponent extends React.Component {};

11. 函数

1. 默认值

// 例子 11-1// badfunction test(quantity) {  const q = quantity || 1;}// goodfunction test(quantity = 1) {  ...}
// 例子 11-2doSomething({ foo: 'Hello', bar: 'Hey!', baz: 42 });// badfunction doSomething(config) {  const foo = config.foo !== undefined ? config.foo : 'Hi';  const bar = config.bar !== undefined ? config.bar : 'Yo!';  const baz = config.baz !== undefined ? config.baz : 13;}// goodfunction doSomething({ foo = 'Hi', bar = 'Yo!', baz = 13 }) {  ...}// betterfunction doSomething({ foo = 'Hi', bar = 'Yo!', baz = 13 } = {}) {  ...}
// 例子 11-3// badconst Button = ({className}) => {    const classname = className || 'default-size';    return <span className={classname}></span>};// goodconst Button = ({className = 'default-size'}) => (    <span className={classname}></span>);// betterconst Button = ({className}) =>    <span className={className}></span>}Button.defaultProps = {    className: 'default-size'}
// 例子 11-4const required = () => {throw new Error('Missing parameter')};const add = (a = required(), b = required()) => a + b;add(1, 2) // 3add(1); // Error: Missing parameter.

12. 拓展运算符

1. arguments 转数组

// 例子 12-1// badfunction sortNumbers() {  return Array.prototype.slice.call(arguments).sort();}// goodconst sortNumbers = (...numbers) => numbers.sort();

2. 调用参数

// 例子 12-2// badMath.max.apply(null, [14, 3, 77])// goodMath.max(...[14, 3, 77])// 等同于Math.max(14, 3, 77);

3. 构建对象

剔除部分属性,将剩下的属性构建一个新的对象

// 例子 12-3let [a, b, ...arr] = [1, 2, 3, 4, 5];const { a, b, ...others } = { a: 1, b: 2, c: 3, d: 4, e: 5 };

有条件的构建对象

// 例子 12-4// badfunction pick(data) {  const { id, name, age} = data  const res = { guid: id }  if (name) {    res.name = name  }  else if (age) {    res.age = age  }  return res}// goodfunction pick({id, name, age}) {  return {    guid: id,    ...(name && {name}),    ...(age && {age})  }}

合并对象

// 例子 12-5let obj1 = { a: 1, b: 2,c: 3 }let obj2 = { b: 4, c: 5, d: 6}let merged = {...obj1, ...obj2};

4. React

将对象全部传入组件

// 例子 12-6const parmas =  {value1: 1, value2: 2, value3: 3}<Test {...parmas} />

13. 双冒号运算符

// 例子 13-1foo::bar;// 等同于bar.bind(foo);foo::bar(...arguments);// 等同于bar.apply(foo, arguments);

如果双冒号左边为空,右边是一个对象的方法,则等于将该方法绑定在该对象上面。

// 例子 13-2var method = obj::obj.foo;// 等同于var method = ::obj.foo;let log = ::console.log;// 等同于var log = console.log.bind(console);

14. 解构赋值

1. 对象的基本解构

// 例子 14-1componentWillReceiveProps(newProps) {    this.setState({        active: newProps.active    })}componentWillReceiveProps({active}) {    this.setState({active})}
// 例子 14-2// badhandleEvent = () => {  this.setState({    data: this.state.data.set("key", "value")  })};// goodhandleEvent = () => {  this.setState(({data}) => ({    data: data.set("key", "value")  }))};
// 例子 14-3Promise.all([Promise.resolve(1), Promise.resolve(2)]).then(([x, y]) => {    console.log(x, y);});

2. 对象深度解构

// 例子 14-4// badfunction test(fruit) {  if (fruit && fruit.name)  {    console.log (fruit.name);  } else {    console.log('unknown');  }}// goodfunction test({name} = {}) {  console.log (name || 'unknown');}
// 例子 14-5let obj = {    a: {      b: {        c: 1      }    }};const {a: {b: {c = ''} = ''} = ''} = obj;

3. 数组解构

// 例子 14-6// badconst spliteLocale = locale.splite("-");const language = spliteLocale[0];const country = spliteLocale[1];// goodconst [language, country] = locale.splite('-');

4. 变量重命名

// 例子 14-8let { foo: baz } = { foo: 'aaa', bar: 'bbb' };console.log(baz); // "aaa"

5. 仅获取部分属性

// 例子 14-9function test(input) {  return [left, right, top, bottom];}const [left, __, top] = test(input);function test(input) {  return { left, right, top, bottom };}const { left, right } = test(input);

15. 增强的对象字面量

// 例子 15-1// badconst something = 'y'const x = {  something: something}// goodconst something = 'y'const x = {  something};

动态属性

// 例子 15-2const x = {  ['a' + '_' + 'b']: 'z'}console.log(x.a_b); // z

16. 数组的拓展方法

1. keys

// 例子 16-1var arr = ["a", , "c"];var sparseKeys = Object.keys(arr);console.log(sparseKeys); // ['0', '2']var denseKeys = [...arr.keys()];console.log(denseKeys);  // [0, 1, 2]

2. entries

// 例子 16-2var arr = ["a", "b", "c"];var iterator = arr.entries();for (let e of iterator) {    console.log(e);}

3. values

// 例子 16-3let arr = ['w', 'y', 'k', 'o', 'p'];let eArr = arr.values();for (let letter of eArr) {  console.log(letter);}

4. includes

// 例子 16-4// badfunction test(fruit) {  if (fruit == 'apple' || fruit == 'strawberry') {    console.log('red');  }}// goodfunction test(fruit) {  const redFruits = ['apple', 'strawberry', 'cherry', 'cranberries'];  if (redFruits.includes(fruit)) {    console.log('red');  }}

5. find

// 例子 16-5var inventory = [    {name: 'apples', quantity: 2},    {name: 'bananas', quantity: 0},    {name: 'cherries', quantity: 5}];function findCherries(fruit) {    return fruit.name === 'cherries';}console.log(inventory.find(findCherries)); // { name: 'cherries', quantity: 5 }

6. findIndex

// 例子 16-6function isPrime(element, index, array) {  var start = 2;  while (start <= Math.sqrt(element)) {    if (element % start++ < 1) {      return false;    }  }  return element > 1;}console.log([4, 6, 8, 12].findIndex(isPrime)); // -1, not foundconsole.log([4, 6, 7, 12].findIndex(isPrime)); // 2

更多的就不列举了。

17.

举个例子:

// 例子 17-1const obj = {  foo: {    bar: {      baz: 42,    },  },};const baz = obj?.foo?.bar?.baz; // 42

同样支持函数:

// 例子 17-2function test() {  return 42;}test?.(); // 42exists?.(); // undefined

需要添加 插件支持

18. logical-assignment-operators

// 例子 18-1a ||= b;obj.a.b ||= c;a &&= b;obj.a.b &&= c;

Babel 编译为:

var _obj$a, _obj$a2;a || (a = b);(_obj$a = obj.a).b || (_obj$a.b = c);a && (a = b);(_obj$a2 = obj.a).b && (_obj$a2.b = c);

出现的原因:

// 例子 18-2function example(a = b) {  // a 必须是 undefined  if (!a) {    a = b;  }}function numeric(a = b) {  // a 必须是 null 或者 undefined  if (a == null) {    a = b;  }}// a 可以是任何 falsy 的值function example(a = b) {  // 可以,但是一定会触发 setter  a = a || b;  // 不会触发 setter,但可能会导致 lint error  a || (a = b);  // 就有人提出了这种写法:  a ||= b;}

需要 插件支持

19. nullish-coalescing-operator

a ?? b// 相当于(a !== null && a !== void 0) ? a : b

举个例子:

var foo = object.foo ?? "default";// 相当于var foo = (object.foo != null) ? object.foo : "default";

需要 插件支持

20. pipeline-operator

const double = (n) => n * 2;const increment = (n) => n + 1;// 没有用管道操作符double(increment(double(5))); // 22// 用上管道操作符之后5 |> double |> increment |> double; // 22

其他

新开了 ,大家可以在更多的平台上看到我的文章,欢迎关注哦~

参考

  1. [[译] 如何使用 JavaScript ES6 有条件地构造对象](

ES6 系列

ES6 系列目录地址:

ES6 系列预计写二十篇左右,旨在加深 ES6 部分知识点的理解,重点讲解块级作用域、标签模板、箭头函数、Symbol、Set、Map 以及 Promise 的模拟实现、模块加载方案、异步处理等内容。

如果有错误或者不严谨的地方,请务必给予指正,十分感谢。如果喜欢或者有所启发,欢迎 star,对作者也是一种鼓励。

原文地址:https://segmentfault.com/a/1190000017171866

转载于:https://www.cnblogs.com/lalalagq/p/10110968.html

你可能感兴趣的文章
磁盘分区和挂载
查看>>
文件修改
查看>>
软退回和硬退回的区别和联系
查看>>
关于异常处理
查看>>
OC 调用JS 代码 处理HTML5 实战
查看>>
LNMP
查看>>
C++读取系统当前时间 分类: C/C++ 2015...
查看>>
实验五
查看>>
Windows启动及停止服务
查看>>
Centos 6.5下mysql 8.0.11的rpm包的安装方式
查看>>
201521123037 《Java程序设计》第10周学习总结
查看>>
小程序的基本原生js使用
查看>>
获取任意元素距离页面顶部的距离 楼梯效果
查看>>
13暑假集训6 总结
查看>>
NGS基础 - 高通量测序原理
查看>>
屏障和屏障属性
查看>>
UML作业第一次:UML用例图绘制
查看>>
Form1.cs
查看>>
bootstrap 垂直菜单栏样式
查看>>
POJ - 2723 Get Luffy Out (二分+2-SAT)
查看>>