[译]ES6特性

原文

作用域

使用let/const替代var

var有什么错?

var说明的变量会产生作用于提升的概念。

ES5:

var x = 'outer';
function test(inner) {
  if (inner) {
    var x = 'inner'; // scope whole function
    return x;
  }
  return x; // gets redefined because line 4 declaration is hoisted
}
test(false); // undefined 😱
test(true); // inner

test(false)返回的是undefined而不是outer

为什么?

因为if-block没有执行,第四行的var x被提升了。

提升后,上面的代码变成了下面的样子:

var x = 'outer';
function test(inner) {
  var x; // 提升到了
  if (inner) {
    x = 'inner'; // 初始化没有提升
    return x;
  }
  return x;
}

ES6中可以这样解决这个问题:

let x = 'outer';
function test(inner) {
  if (inner) {
    let x = 'inner';
    return x;
  }
  return x; // gets result from line 1 as expected
}
test(false); // outer
test(true); // inner

var改为let后,返回的就是如你所愿的outer了。如果if block没有调用,x变量也不会提升了。

IIFE

ES5:

{
  var private = 1;
}
console.log(private); // 1

可以看到private暴露出来了。为了不暴露它,你需要用IIFE包裹住它:
ES5

(function(){
  var private2 = 1;
})();
console.log(private2); // Uncaught ReferenceError

如果你看过jQuery/lodash的源码,你会发现它们都使用了IIFE来避免全局变量污染。

在ES6中解决这个问题简单许多,不需要再使用IIFE了,我们只需要使用block和let
ES6:

{
  let private3 = 1;
}
console.log(private3); // Uncaught ReferenceError

const

如果有个变量你永远都不想它改变的话,你可以使用const

模板字面量

ES5:

var first = 'Adrian';
var last = 'Mejia';
console.log('Your name is ' + first + ' ' + last + '.');

在ES6中,我们可以使用${}来代替+:

const first = 'Adrian'
const last = 'Mejia'
console.log('Your name is ${first} ${last}.');

多行字符串

不再需要像下面一样使用 +\n了。
ES5:

var template = '<li *ngFor="let todo of todos" [ngClass]="{completed: todo.isDone}" >\n' +
'  <div class="view">\n' +
'    <input class="toggle" type="checkbox" [checked]="todo.isDone">\n' +
'    <label></label>\n' +
'    <button class="destroy"></button>\n' +
'  </div>\n' +
'  <input class="edit" value="">\n' +
'</li>';
console.log(template);

在ES6中使用反引号来解决这个问题:

const template = `<li *ngFor="let todo of todos" [ngClass]="{completed: todo.isDone}" >
  <div class="view">
    <input class="toggle" type="checkbox" [checked]="todo.isDone">
    <label></label>
    <button class="destroy"></button>
  </div>
  <input class="edit" value="">
</li>`;
console.log(template);

解构赋值

获取一个数组中的元素

ES5:

var array = [1, 2, 3, 4, 5];

var first = array[0];
var third = array[2];

console.log(first, third); // 1 3

ES6:

const array = [1, 2, 3, 4, 5];

const [first, ,third] = array;

console.log(first, third); // 1 3

交换变量

ES5:

var a = 1;
var b = 2;

var temp = a;
a = b;
b = temp;

console.log(a, b); // 2 1

ES6:

let a = 1;
let b = 2;

[a, b] = [b, a];

console.log(a, b); // 2 1

解构多个返回值

ES5:

function margin() {
  var left=1, right=2, top=3, bottom=4;
  return { left: left, right: right, top: top, bottom: bottom };
}
var data = margin();
var left = data.left;
var bottom = data.bottom;
console.log(left, bottom); // 1 4

在ES6中,调用者可以从选择的选取返回数据(第6行):
ES6:

function margin() {
  const left=1, right=2, top=3, bottom=4;
  return { left, right, top, bottom };
}
const { left, bottom } = margin();
console.log(left, bottom); // 1 4

注意第3行,我们可以将{ left: left }简写为{ left }

解构参数匹配

ES5:

var user = {firstName: 'Adrian', lastName: 'Mejia'};
function getFullName(user) {
  var firstName = user.firstName;
  var lastName = user.lastName;
  return firstName + ' ' + lastName;
}
console.log(getFullName(user)); // Adrian Mejia

ES6:

const user = {firstName: 'Adrian', lastName: 'Mejia'};
function getFullName({ firstName, lastName }) {
  return `${firstName} ${lastName}`;
}
console.log(getFullName(user)); // Adrian Mejia

解构对象

ES5:

function settings() {
  return { display: { color: 'red' }, keyboard: { layout: 'querty'} };
}
var tmp = settings();
var displayColor = tmp.display.color;
var keyboardLayout = tmp.keyboard.layout;
console.log(displayColor, keyboardLayout); // red querty

ES6:

function settings() {
  return { display: { color: 'red' }, keyboard: { layout: 'querty'} };
}
const { display: { color: displayColor }, keyboard: { layout: keyboardLayout }} = settings();
console.log(displayColor, keyboardLayout); // red querty

最佳练习

  • 使用解构数组来获取数组中的元素或交换变量。这将减少创建临时变量。
  • 不要使用解构数组来获取多个返回值,使用解构对象来获取多个返回值。

类和对象

在ES6中,我们不再使用构造函数Function,而是使用class

在ES5中,我们使用构造函数Function来实现OOP。
ES5:

var Animal = (function () {
  function MyConstructor(name) {
    this.name = name;
  }
  MyConstructor.prototype.speak = function speak() {
    console.log(this.name + ' makes a noise.');
  };
  return MyConstructor;
})();
var animal = new Animal('animal');
animal.speak(); // animal makes a noise.

ES6提供了classconstructor关键字来实现类。同时使用speak()来替代constructor.prototype.speak = function() {}
ES6:

class Animal {
  constructor(name) {
    this.name = name;
  }
  speak() {
    console.log(this.name + ' makes a noise.');
  }
}
const animal = new Animal('animal');
animal.speak(); // animal makes a noise.

继承

在ES5中,使用原型链来实现继承。
ES5:

var Lion = (function () {
  function MyConstructor(name){
    Animal.call(this, name);
  }
  // prototypal inheritance
  MyConstructor.prototype = Object.create(Animal.prototype);
  MyConstructor.prototype.constructor = Animal;
  MyConstructor.prototype.speak = function speak() {
    Animal.prototype.speak.call(this);
    console.log(this.name + ' roars 🦁');
  };
  return MyConstructor;
})();
var lion = new Lion('Simba');
lion.speak(); // Simba makes a noise.
// Simba roars.

ES6提供了extendssuper关键字。
ES6:

class Lion extends Animal {
  speak() {
    super.speak();
    console.log(this.name + ' roars 🦁');
  }
}
const lion = new Lion('Simba');
lion.speak(); // Simba makes a noise.
// Simba roars.

原生的Promise

ES5:

function printAfterTimeout(string, timeout, done){
  setTimeout(function(){
    done(string);
  }, timeout);
}
printAfterTimeout('Hello ', 2e3, function(result){
  console.log(result);
  // nested callback
  printAfterTimeout(result + 'Reader', 2e3, function(result){
    console.log(result);
  });
});

ES6:

function printAfterTimeout(string, timeout){
  return new Promise((resolve, reject) => {
    setTimeout(function(){
      resolve(string);
    }, timeout);
  });
}
printAfterTimeout('Hello ', 2e3).then((result) => {
  console.log(result);
  return printAfterTimeout(result + 'Reader', 2e3);
}).then((result) => {
  console.log(result);
});

箭头函数

在ES5中this有些问题:
ES5:

var _this = this; // need to hold a reference
$('.btn').click(function(event){
  _this.sendData(); // reference outer this
});
$('.input').on('change',function(event){
  this.sendData(); // reference outer this
}.bind(this)); // bind to outer this

需要使用一个临时变量或者bind来绑定this。在ES6中,你可以使用箭头函数。
ES6:

// this will reference the outer one
$('.btn').click((event) =>  this.sendData());
// implicit returns
const ids = [291, 288, 984];
const messages = ids.map(value => `ID is ${value}`);

for of

ES6中提供了for of
ES5:

// for
var array = ['a', 'b', 'c', 'd'];
for (var i = 0; i < array.length; i++) {
  var element = array[i];
  console.log(element);
}
// forEach
array.forEach(function (element) {
  console.log(element);
});

ES6:

// for ...of
const array = ['a', 'b', 'c', 'd'];
for (const element of array) {
    console.log(element);
}

参数默认值

ES5:

function point(x, y, isFlag){
  x = x || 0;
  y = y || -1;
  isFlag = isFlag || true;
  console.log(x,y, isFlag);
}
point(0, 0) // 0 -1 true 😱
point(0, 0, false) // 0 -1 true 😱😱
point(1) // 1 -1 true
point() // 0 -1 true

ES6:

function point(x = 0, y = -1, isFlag = true){
  console.log(x,y, isFlag);
}
point(0, 0) // 0 0 true
point(0, 0, false) // 0 0 false
point(1) // 1 -1 true
point() // 0 -1 true

Rest parameters

ES5:

function printf(format) {
  var params = [].slice.call(arguments, 1);
  console.log('params: ', params);
  console.log('format: ', format);
}
printf('%s %d %.2f', 'adrian', 321, Math.PI);

ES6提供了...操作符。
ES6:

function printf(format, ...params) {
  console.log('params: ', params);
  console.log('format: ', format);
}
printf('%s %d %.2f', 'adrian', 321, Math.PI);

展开操作符(Spread operator)

ES5:

Math.max.apply(Math, [2,100,1,6,43]) // 100

ES6:

Math.max(...[2,100,1,6,43]) // 100

同样适用...来替代concat。

ES5:

var array1 = [2,100,1,6,43];
var array2 = ['a', 'b', 'c', 'd'];
var array3 = [false, true, null, undefined];
console.log(array1.concat(array2, array3));

ES6:

const array1 = [2,100,1,6,43];
const array2 = ['a', 'b', 'c', 'd'];
const array3 = [false, true, null, undefined];
console.log([...array1, ...array2, ...array3]);
posted @ 2017-07-03 09:06  irocker  阅读(319)  评论(0编辑  收藏  举报