Skip to content

Latest commit

 

History

History
445 lines (322 loc) · 11.1 KB

File metadata and controls

445 lines (322 loc) · 11.1 KB

ES6

Proposals



Tools

indexOf uses Strict Equality Comparison. See SameValueZero comparison.

Objects in JavaScript have reference equality.

{error: error} === {error}

String

String.prototype.includes
String.prototype.startsWith(txt, start)
String.prototype.endsWith(txt, end)
String.prototype.repeat(count)
String.prototype.trim()

Import and Export

class Radio {}

export { Radio as Player };

import { Player as SportsPlayer } from 'radio';
var basketball = new SportsPlayer();

Killer Features is Multiple Exports

CJS and AMD can only export one thing. Historically, we've worked around that by exporting an object with lots of things - for example, Underscore exports the _ object with lots of functions attached:

var _ = {
  where: fn,
  memoize: fn,
  pluck: fn
};

This single export make it hard to do tree-shaking and choose only the right amount of modules to bundle to decrease file size.

Class

Class, unlike function is not hoisted, so you have to declared it before using it.

You have to call super before you can use access this.

Template String

Can be a security concern if you allow user to input template string.

Block scope

if (x > y) {
  var tmp = x;
  x = y;
  y = tmp;
}
console.log(tmp === x); // true

if (x > y) {
  let tmp = x;
  x = y;
  y = tmp;
}
console.log(tmp === x); // ReferenceError: tmp is not defined

Destructuring

Extract data from arrays or objects using syntax that "mirrors" the construction of array and object literals.

// Array destructuring
let [x, y] = ['a', 'b']; //=> x=a, y=b

let [x, y, ...rest] = ['a', 'b', 'c', 'd']; //=> rest = ['c', 'd']

[x, y] = [y, x]; // swap values
// Object destructuring
var o = {p: 42, q: true};
var {p, q} = o; // Means o.p and o.q

const { visible, className, tag } = this.props
let { city: c, state: s } = getAddress(); //=> c will be obj.city

// Can also used in function with default value
function random({ min=1, max=200 } = {}) {
  return Math.floor(Math.random() * (max - min)) + min;
}

// Rest Properties
let { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 };
x; // 1
y; // 2
z; // { a: 3, b: 4 }
// Destructuring in module loading
const {clone, assign} = require('lodash'); // Means _.clone and _.assign

function makeRequest(url, method, params) {
  var config = {url, method, params};

  // Same as
  var config = {
    url: url,
    method: method,
    params: params
  }
}

Spread Operator

A better apply and a better push.

// Easier concatenation
[1, 2, ...[3, 4, 5], 6, 7]

Can be used for destructuring also.

[..."abc"] // Will become [ 'a', 'b', 'c' ]
[...document.querySelectorAll('div')] // Same, will give you [<div>, <div>, <div>]

// Which is a better apply, because console.log() function take in argument with comma
console.log(...[1, 2, 3])

var a = [1, 2, 3];
var b = [...a, 4, 5];

// For destructuring
var a, b, c;
[a, b, ...c] = [1, 2, 3, 4, 5];

// With function

function bar(a, b, c) {
}

var args = [1, 2, 3];
bar(...args);

function bar(a, ...params) {
}

// Spread Properties
let n = { x, y, ...z }
n; // { x: 1, y: 2, a: 3, b: 4 }

// Unknown props example
// See https://facebook.github.io/react/warnings/unknown-prop.html
function MyDiv(props) {
  // We filter out the layout property
  const { layout, ...rest } = props;
  return <div {...rest} style="demo">Test</div>
}

Object.assign, Cloning, Extending

// Making a shallow copy
let copy = { ...original }

// Merge several different objects
let merged = { ...foo, ...bar, ...baz }

// Add new properties in the process of merging
let newObj = {
  title: 'hello',
  ...foo,
  world: 200,
  ...bar
}

Object rests are the dual of object spreads, in that they can extract any extra properties that don't get picked up when destructuring an element.

// If you want to remove irrelevant props
render() {
  switch(this.props.size) {
    // do something with size prop
  }
  
  var attrs = Object.assign({}, this.props); // shallow clone
  delete attrs.size;
  
  return <a {...attrs}>{this.props.children}</a>;
}

// Or you can use ES7
render() {
  var {size, ...attrs} = this.props;

  switch(this.props.size) {
    // do something with size prop
  }
  
  return <a {...attrs}>{this.props.children}</a>;
}

// 
deleteComment(comment) {
  $.ajax.delete(comment);

  // clone using spread operator  
  const comments = [...this.state.comments];
  const commentIndex = comments.indexOf(comment);
  comments.splice(commentIndex, 1);
  this.setState({ comments });
}
<Something {...propsA} propB="B" />

// Spread attributes actually use Object.assign

React.createElement(Something, Object.assign({}, propsA, {propB: 'B'}))

Reduce

var a = Object.keys(toggleStates).reduce((newStates, key) => {
	newStates[key] = !toggleAll;
	return newStates;
}, {});

// Same as
var six = [1, 2, 3].reduce((sum, n) => {
	return sum + n;
}, 0);

Decorators

Mixin is just metaobject?

Mixin application should create a new class (metaclass) by composing existing ones.

Iterators

forEach, for-in, for-of and iterators

React

import React from 'react';
import autobind from 'autobind-decorator';

let { PropTypes, Component } = React;

@autobind
class Person extends Component {
  // Use constructor instead of componentWillMount()
  constructor(...args) {
    super(...args);
    // No more getInitialState
    this.state = {
      name: props.name
    };
    
    // If you do not want to use ES8 to bind event
    this.handleClick = this.handleClick.bind(this)
  }
  
  // ES7 property initializers
  state = { isEditing: false };
  
  static defaultProps = { initialCount: 0 };
  static propTypes = {
    user: React.PropTypes.object.isRequired
  }
  
  // ES8 - Good for event handler and callback which need binding
  // See https://daveceddia.com/avoid-bind-when-passing-props/
  change = env => this.setState({isEditing: true});
  
  // Combining 2 features: Arrow function + property initializers
  handleClick = (e) => this.setState()
  
  setName(name) {
    this.setState({ name: name });
  }
  
  handleChange(name, e) {
    var newState = {};
    newState[name] = e.target.value;
    this.setState(newState);
    
    // Or you can
    this.setState({
      [name]: e.target.value
    });
  }
    
  render() {
    return();
  }
}

// ES6, not ES7
Person.propTypes = {
  items: PropTypes.array.isRequired
};

// No more getDefaultProps
Person.defaultProps = { name: 'anonymous' };

export default Person;

Generator

A generator is basically a function whose execution can be paused and then resumed later, remembering its state.

ES7 introduce the async and await keywords, removing the need for a generator library altogether.

Generators don't have to terminate which make it very useful.

function *myGen(x) {
  yield x;
}

var iterator = myGen();
iterator.next();

Async and Await

// Using Alt.js
async login(data) {
  try {
    const response = await axios.post('/login', data);
    this.dispatch({ok: true, user: response.data});
  } catch (err) {
    this.dispatch({ok: false, error: err.data});
  }
}

Reflect and Proxy

Function.prototype.apply.call(f, obj, args);

Reflect.apply(f, obj, args);

Concise Methods and Lexical Identifier

DOM