ES6

ECMAScript 6,也叫 ES6 或 ES2015。

JavaScript 自 1995 年面世,1997 年成立的 ECMAScript 引领着 JavaScript 的发展。已发布的版本 ES3、 ES5、 ES6 。

  • JavaScript 进化史

ES3 与 ES5 之间隔了 10 年,而ES5 与 ES6 之间隔了 6 年。改进的新模式是每年都渐进式地做一些小改动,而不是像 ES6 一样一次性地进行大量的更改。

  • 浏览器支持

大部分都已可以使用

ES6 新增优势

  • 块级作用域变量let const

var 定义的变量会泄露到其它代码块,比如 for 循环或是 if 块。

(详见let和const语法)

  • IIFE

在ES5中


{

 var private = 1;

}

console.log(private); // 1

private 会发生泄漏。需要使用 IIFE(立即执行函数表达式)将其包起来:


(function(){

 var private2 = 1;

})();

console.log(private2); // Uncaught ReferenceError

jQuery等开源项目的源代码,它们都利用了 IIFE,以避免污染全局环境,而只在全局下定义 _、$或是 jQuery。

而在ES6中

{

 let private3 = 1;

}

console.log(private3); // Uncaught ReferenceError

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}.`);
  • 多行字符串也同样可以使用反引号连接

  • ES6 解构非常简明并且好用

ES5

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

var first = array[0];

var third = array[2];

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

等同于:

ES6

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

const [first, ,third] = array;

console.log(first, third); // 1 3
  • 调换值

ES5

var a = 1;

var b = 2;

var tmp = a;

a = b;

b = tmp;

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

在第3行,也可以像这样用数组返回(并保存序列):

return [left, right, top, bottom];

但之后调用时需要考虑返回数据的顺序。

var left = data[0];

var bottom = data[3];

ES6 中调用时只会选择需要的数据(第 6 行):

1. function margin() {

2  const left=1, right=2, top=3, bottom=4;

3  return { left, right, top, bottom };

4 }

5 const { left, bottom } = margin();

6 console.log(left, bottom); // 1 4


注意:第3行用到了一些其它的 ES6 功能。可以将 { 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 用“类”替代“构造函数”。

在 JavaScript 中,每个对象都有原型对象。所有 JavaScript 对象都从原型上继承方法和属性。

ES5 以面向对象编程的方式创建对象,是利用构造函数实现的:

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 可以用 class、constructor 等新的关键字、更少的样板代码实现相同的效果。同样可以看到相比于constructor.prototype.speak = function (),用 speak() 定义方法更加清晰:

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.

用 class 语法,避免直接操作 prototype.

避免出现空的构造器。如果没有指明,类会有默认的构造器的。

  • 继承

基于前面的 Animal 类,现在想要拓展 Animal,定义一个 Lion 类。

ES5

var Lion = (function () {

 function MyConstructor(name){

   Animal.call(this, name);

 }

 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

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.


使用内置的 extends 实现继承。

原生 Promise

用 promise 替代回调地狱

ES5

function printAfterTimeout(string, timeout, done){

 setTimeout(function(){

   done(string);

 }, timeout);

}

printAfterTimeout('Hello ', 2000, function(result){

 console.log(result);

 // nested callback

 printAfterTimeout(result + 'Reader', 2000, function(result){

   console.log(result);

 });

});

这个函数接收一个回调,在 done 后执行。我们想要先后执行两次,所以在回调中又一次调用了 printAfterTimeout。

如果需要多次回调。用 promise 实现

ES6

function printAfterTimeout(string, timeout){

 return new Promise((resolve, reject) => {

   setTimeout(function(){

     resolve(string);

   }, timeout);

 });

}

printAfterTimeout('Hello ', 2000).then((result) => {

 console.log(result);

 return printAfterTimeout(result + 'Reader', 2000);

}).then((result) => {

 console.log(result);

});
  • 箭头函数

ES6 没有移除函数表达式,但是新增了箭头函数。

ES5 this的指向

var _this = this; // 

$('.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

在函数内,需要用临时变量指向 this 或者使用 bind 绑定。ES6 中可以使用箭头函数。

For…of

最开始用 for ,然后使用 forEach,而现在可以用 for…of:

ES6


$('.btn').click((event) =>  this.sendData());

// implicit returns

const ids = [291, 288, 984];

const messages = ids.map(value => `ID is ${value}`);

ES6 的 for…of 也可以用来迭代。

默认参数

之前需要检测变量是否定义了,而现在可以指定 default parameters 的值。

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//我们传的值是 0, 0 但是得到的是 0, -1


point(0, 0, false) // 0 -1 true//传进去 false 但是得到的是 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

ES5 是因为先要检测 undefined的值,而 false、 null、 undefined 和 0 都是假的值。我们可以加些代码:

ES5

function point(x, y, isFlag){

 x = x || 0;

 y = typeof(y) === 'undefined' ? -1 : y;

 isFlag = typeof(isFlag) === 'undefined' ? true : isFlag;

 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

现在当检测 undefined 值时就符合我们的要求了。

之前使用 arguments,而现在可以用展开操作符。

现在可以用展开操作符 ... 达到相同的目的。

ES6

function printf(format, ...params) {

 console.log('params: ', params);

 console.log('format: ', format);

}

printf('%s %d %.2f', 'adrian', 321, Math.PI);

展开操作符...

之前用 apply(),现在可以方便地使用展开操作符 ... 了:

提示:apply() 可以将数组转化为一系列参数。例如 Math.max() 接收一系列参数,但如果想应用于数组的话可以用 apply 帮助实现。

如上所述,apply 可以将数组当作参数序列进行传递:

ES5

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

ES6 可以用展开操作符:

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 可以用展开操作符展开嵌套的数组:

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])
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,902评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,037评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,978评论 0 332
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,867评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,763评论 5 360
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,104评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,565评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,236评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,379评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,313评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,363评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,034评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,637评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,719评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,952评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,371评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,948评论 2 341

推荐阅读更多精彩内容

  • 三,字符串扩展 3.1 Unicode表示法 ES6 做出了改进,只要将码点放入大括号,就能正确解读该字符。有了这...
    eastbaby阅读 1,505评论 0 8
  • 函数参数的默认值 基本用法 在ES6之前,不能直接为函数的参数指定默认值,只能采用变通的方法。 上面代码检查函数l...
    呼呼哥阅读 3,347评论 0 1
  • 1.函数参数的默认值 (1).基本用法 在ES6之前,不能直接为函数的参数指定默认值,只能采用变通的方法。
    赵然228阅读 677评论 0 0
  • 官方中文版原文链接 感谢社区中各位的大力支持,译者再次奉上一点点福利:阿里云产品券,享受所有官网优惠,并抽取幸运大...
    HetfieldJoe阅读 3,020评论 3 37
  • 【小花涵涵】学习力四期践行记录D17 20161210 今天中午吃完饭无意间经过婚纱一条街时,宝贝对橱窗里的新娘装...
    夏苏的花园阅读 197评论 0 0