内容:

1.ES6介绍及基础

2.模块、类和继承

3.ES6高级特性

4.Generator和Iterator

5.异步编程

6.函数相关

内容参考:《ES6 标准入门》

ES6标准阅读链接:http://es6.ruanyifeng.com/

一、ES6介绍及基础

1.什么是ES6

ECMAScript 6.0(以下简称 ES6)是 JavaScript 语言的下一代标准,已经在 2015 年 6 月正式发布了。它的目标,是使得 JavaScript 语言可以用来编写复杂的大型应用程序,成为企业级开发语言

2.JavaScript版本

JavaScript有很多版本,具体版本如下:

3.let和const

(1)let

ES6 新增了let命令,用来声明变量。它的用法类似于varlet所声明的变量,只在let命令所在的代码块内有效,也就是说let创建块级作用域

let和var的区别:

 {
let a = 10;
var b = 1;
} console.log(a) // ReferenceError: a is not defined.
console.log(b) //
// 结果表明,let声明的变量只在它所在的代码块有效 // var和let的区别:
// 下面的代码如果使用var,最后输出的是10:
var a = [];
for (var i = 0; i < 10; i++) {
a[i] = function () {
console.log(i);
};
}
a[6]() // // 如果使用let,声明的变量仅在块级作用域内有效,最后输出的是 6。
var a = [];
for (let i = 0; i < 10; i++) {
a[i] = function () {
console.log(i);
};
}
a[6]() //

for循环的特别之处:

 // 设置循环变量的那部分是一个父作用域,而循环体内部是一个单独的子作用域
// 例如下面这段代码:
for (let i = 0; i < 3; i++) {
let i = 'abc';
console.log(i);
}
// abc
// abc
// abc

另外,var命令会发生”变量提升“现象,即变量可以在声明之前使用,值为undefined。这种现象多多少少是有些奇怪的,按照一般的逻辑,变量应该在声明语句之后才可以使用。

为了纠正这种现象,let命令改变了语法行为,它所声明的变量一定要在声明后使用,否则报错

 // var 的情况
console.log(foo); // 输出undefined
var foo = 2; // let 的情况
console.log(bar); // 报错ReferenceError
let bar = 2;

(2)const

const声明一个只读常量;const一旦声明就必须立即初始化,不能留到以后赋值;const作用域与let相同:只在所在的块级作用域内有效

 const PI = 3.1415;
PI // 3.1415 PI = 3;
// TypeError: Assignment to constant variable.
// 改变常量的值会报错 const foo;
// SyntaxError: Missing initializer in const declaration
// const 用来声明一个不可赋值的变量  变量的值只能在声明的时候赋予
const a = 1
a = 2 // 错误 // 下面的不是赋值 是操作 所以是可以的
const arr = [1, 2]
arr.push(3)
// [1, 2, 3]

二、模块、类和继承

1.模块module

历史上,JavaScript 一直没有模块(module)体系,无法将一个大程序拆分成互相依赖的小文件,再用简单的方法拼装起来。其他语言都有这项功能,比如 Ruby 的require、Python 的import,甚至就连 CSS 都有@import,但是 JavaScript 任何这方面的支持都没有,这对开发大型的、复杂的项目形成了巨大障碍

在 ES6 之前,社区制定了一些模块加载方案,最主要的有 CommonJS 和 AMD 两种。前者用于服务器,后者用于浏览器。ES6 在语言标准的层面上,实现了模块功能,而且实现得相当简单,完全可以取代 CommonJS 和 AMD 规范,成为浏览器和服务器通用的模块解决方案;ES6 模块的设计思想是尽量的静态化,使得编译时就能确定模块的依赖关系,以及输入和输出的变量。CommonJS 和 AMD 模块,都只能在运行时确定这些东西。比如,CommonJS 模块就是对象,输入时必须查找对象属性

ES6 模块不是对象,而是通过export命令显式指定输出的代码,再通过import命令输入:

 // export
export function stat() {}
export function exists() {}
export function readFile () {}
// import
import { stat, exists, readFile } from 'fs';

上面代码的实质是从fs模块加载 3 个方法,其他方法不加载。这种加载称为“编译时加载”或者静态加载,即 ES6 可以在编译时就完成模块加载,效率要比 CommonJS 模块的加载方式高

模块详细内容:http://es6.ruanyifeng.com/#docs/module

2.类class

下面是ES5和ES6定义类的写法:

 // ES5:
function Point(x, y) {
this.x = x;
this.y = y;
} Point.prototype.toString = function () {
return '(' + this.x + ', ' + this.y + ')';
}; var p = new Point(1, 2); //ES6:
class Point {
constructor(x, y) {
this.x = x;
this.y = y;
} toString() {
return '(' + this.x + ', ' + this.y + ')';
}
}

类详细介绍:http://es6.ruanyifeng.com/#docs/class

3.继承inherit

ES6中Class 可以通过extends关键字实现继承,这比 ES5 的通过修改原型链实现继承,要清晰和方便很多

 class Point {
constructor(x, y) {
this.x = x;
this.y = y;
}
} class ColorPoint extends Point {
constructor(x, y, color) {
super(x, y); // 调用父类的constructor(x, y)
this.color = color;
} toString() {
return this.color + ' ' + super.toString(); // 调用父类的toString()
}
}

继承详细内容:http://es6.ruanyifeng.com/#docs/class-extends

三、ES6高级特性

1.变量的解构赋值

ES6中允许这样的赋值方式:

 1 let [a, b, c] = [1, 2, 3]
2
3 let [foo, [[bar], baz]] = [1, [[2], 3]];
4 foo // 1
5 bar // 2
6 baz // 3
7
8 let [ , , third] = ["foo", "bar", "baz"];
9 third // "baz"
10
11 let [x, , y] = [1, 2, 3];
12 x // 1
13 y // 3
14
15 let [head, ...tail] = [1, 2, 3, 4];
16 head // 1
17 tail // [2, 3, 4]
18
19 let [x, y, ...z] = ['a'];
20 x // "a"
21 y // undefined
22 z // []

另外如果解析不成功,值就为undefined,如下所示:

1 let [foo] = [];
2 let [bar, foo] = [1];
3 // 以上两种情况都属于解构不成功,foo的值都会等于undefined

更多细节:http://es6.ruanyifeng.com/#docs/destructuring

2.spread 和 rest

(1)拓展运算符spread

spread运算符用于数组的构造,析构,以及在函数调用时使用数组填充参数列表

 let arrs1 = ['aa', 'bb']
let arrs2 = ['cc', 'dd'] // 合并数组
let arrs = [...arrs1, ...arrs2]
console.log(arrs) // ['aa', 'bb', 'cc', 'dd'] // 析构数组
let param1, param2
[param1, ...param2] = arrs1 console.log(param1) // aa
console.log(param2) // ['bb']

(2)剩余运算符rest

rest运算符用于获取函数调用时传入的参数

 function testFunc(...args) {
console.log(args); // ['aa', 'bb', 'cc']
console.log(args.length); //
}
// 调用函数
testFunc('aa', 'bb', 'cc');

剩余运算符rest实现多参数:

 function callFriends(via, ...friends) {
console.log('使用' + via + '通知: ' + friends.join(',') + '等' + friends.length + '个好友')
}
callFriends('QQ', '张三')
callFriends('电话', '张三', '李四', '王五') // 输出结果:
// 使用QQ通知: 张三等1个好友
// 使用电话通知: 张三,李四,王五等3个好友

3.template

模板字符串(template string)是增强版的字符串,用反引号(`)标识。它可以当作普通字符串使用,也可以用来定义多行字符串,或者在字符串中嵌入变量

 // 传统的 JavaScript 语言,输出模板通常是这样写的(下面使用了 jQuery 的方法)。

 $('#result').append(
'There are <b>' + basket.count + '</b> ' +
'items in your basket, ' +
'<em>' + basket.onSale +
'</em> are on sale!'
); // 上面这种写法相当繁琐不方便,ES6 引入了模板字符串解决这个问题。
$('#result').append(`
There are <b>${basket.count}</b> items
in your basket, <em>${basket.onSale}</em>
are on sale!
`);

4.set和map

JavaScript中set和map这两种数据结构详细介绍:http://es6.ruanyifeng.com/#docs/set-map

(1)set

Set 在其他语言里面称为集合,是一种和 Array 相似的数据结构,不同之处在于, Set 中的元素都是不重复的,set 类型的主要作用是去重
用法如下:

 var s = new Set()

 // add 方法添加元素, 和 push 一样
s.add(1)
s.add(2) // has 方法检查元素是否在 set 中
s.has(1) // true
s.has(3) // false // size 属性相当于 length
s.size // // delete 方法删除一个元素
s.delete(1)
s.has(1) s.size //

注:JavaScript中的set不像python中的set那样提供了一系列的运算方法,这些运算方法需要自己去实现

(2)map

Map 和 Object 很相似,在其他语言中 通常会有 dict 和 object 两种数据结构
现在 js 也有独立的 dict 那就是 Map(其实没多好用),其用法如下:

 var m = new Map()

 // set 方法增加一个值
m.set('name', 'gua') // get 属性得到一个值
m.get('name')

四、Generator和Iterator和Decorator

1.generator 

(1)generator -> 类似python的生成器

Generator函数是 ES6 提供的一种异步编程解决方案,语法行为与传统函数完全不同

Generator函数有多种理解角度:

  • 语法上,Generator 函数可以理解为是一个状态机,封装了多个内部状态
  • 执行 Generator 函数会返回一个遍历器对象即Generator 函数还是一个遍历器对象生成函数。返回的遍历器对象可遍历Generator函数内部的每个状态
  • 形式上Generator函数是一个普通函数,但是有两个特征。一是,function关键字与函数名之间有一个星号;二是,函数体内部使用yield表达式,定义不同的内部状态(yield在英语里的意思就是“产出”)

(2)generator函数语法

generator函数如下:

 function* helloWorldGenerator() {
yield 'hello'
yield 'world'
return 'ending'
} var hw = helloWorldGenerator()

Generator 函数的调用方法与普通函数一样,也是在函数名后面加上一对圆括号。不同的是,调用 Generator 函数后,该函数并不执行,返回的也不是函数运行结果,而是一个指向内部状态的指针对象,也就是上一章介绍的遍历器对象(Iterator Object)

下一步,必须调用遍历器对象的next方法,使得指针移向下一个状态。也就是说,每次调用next方法,内部指针就从函数头部或上一次停下来的地方开始执行,直到遇到下一个yield表达式(或return语句)为止。换言之,Generator 函数是分段执行的,yield表达式是暂停执行的标记,而next方法可以恢复执行

 hw.next()
// { value: 'hello', done: false } hw.next()
// { value: 'world', done: false } hw.next()
// { value: 'ending', done: true } hw.next()
// { value: undefined, done: true }

关于generator详细内容:http://es6.ruanyifeng.com/#docs/generator

2.iterator

(1)iterator -> 类似python中的迭代器

JavaScript 原有的表示集合的数据结构,主要是数组和对象,ES6 又添加了MapSet。这样就有了四种数据集合,需要一种统一的接口机制,来处理所有不同的数据结构。

遍历器(Iterator)就是这样一种机制。它是一种接口,为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署 Iterator 接口,就可以完成遍历操作

Iterator 的作用有三个:

  • 为各种数据结构,提供一个统一的、简便的访问接口
  • 使得数据结构的成员能够按某种次序排列
  • ES6 创造了一种新的遍历命令for...of循环,Iterator 接口主要供for...of消费

(2)Iterator 的遍历过程

  • 创建一个指针对象,指向当前数据结构的起始位置。也就是说,遍历器对象本质上,就是一个指针对象。
  • 第一次调用指针对象的next方法,可以将指针指向数据结构的第一个成员。
  • 第二次调用指针对象的next方法,指针就指向数据结构的第二个成员。
  • 不断调用指针对象的next方法,直到它指向数据结构的结束位置。

每一次调用next方法,都会返回数据结构的当前成员的信息。具体来说,就是返回一个包含valuedone两个属性的对象。其中,value属性是当前成员的值,done属性是一个布尔值,表示遍历是否结束

下面是一个模拟next方法返回值的例子:

 var it = makeIterator(['a', 'b']);

 it.next() // { value: "a", done: false }
it.next() // { value: "b", done: false }
it.next() // { value: undefined, done: true } function makeIterator(array) {
var nextIndex = 0;
return {
next: function() {
return nextIndex < array.length ?
{value: array[nextIndex++], done: false} :
{value: undefined, done: true};
}
};
}

关于iterator详细内容:http://es6.ruanyifeng.com/#docs/iterator

3.Decorator

(1)decorator -> 类似python中的装饰器

许多面向对象的语言都有修饰器(Decorator)函数,用来修改类的行为;装饰器是一个对类进行处理的函数。装饰器函数的第一个参数,就是所要修饰的目标类,当然也可以不写成函数调用的方式(见下面的代码)

 @testable  // 等同于testable = testable(MyTestableClass)
class MyTestableClass {
// ...
} function testable(target) {
target.isTestable = true;
} MyTestableClass.isTestable // true // 上面代码中,@testable就是一个修饰器
// 它修改了MyTestableClass类的行为,为它加上静态属性isTestable。testable函数的参数target是MyTestableClass类本身

(2)decorator修饰类的属性

 class Person {
@readonly
name() { return `${this.first} ${this.last}` }
} function readonly(target, name, descriptor){
// descriptor对象原来的值如下
// {
// value: specifiedFunction,
// enumerable: false,
// configurable: true,
// writable: true
// };
descriptor.writable = false;
return descriptor;
} readonly(Person.prototype, 'name', descriptor);
// 类似于
Object.defineProperty(Person.prototype, 'name', descriptor);

关于decorator的详细内容:http://es6.ruanyifeng.com/#docs/decorator

五、异步编程

1.JavaScript中的异步编程

至少在语言级别上,Javascript是单线程的,因此异步编程对其尤为重要。

拿nodejs来说,外壳是一层js语言,这是用户操作的层面,在这个层次上它是单线程运行的,也就是说我们不能像Java、Python这类语言在语言级别使用多线程能力。取而代之的是,nodejs编程中大量使用了异步编程技术,这是为了高效使用硬件,同时也可以不造成同步阻塞。不过nodejs在底层实现其实还是用了多线程技术,只是这一层用户对用户来说是透明的,nodejs帮我们做了几乎全部的管理工作,我们不用担心锁或者其他多线程编程会遇到的问题,只管写我们的异步代码就好

ES 6以前:

  • 回调函数
  • 事件监听(事件发布/订阅)
  • Promise对象

ES 6之后:

  • Generator函数(协程coroutine)
  • async和await

2.callback(回调函数)

假定有两个函数f1和f2,后者等待前者的执行结果:

 f1();
f2();

如果f1是一个很耗时的任务,可以考虑改写f1,把f2写成f1的回调函数:

 function f1(callback){
setTimeout(function () {
// f1的任务代码
callback();
}, 1000);
}

执行代码就变成这样:f1(f2);

采用这种方式,我们把同步操作变成了异步操作,f1不会堵塞程序运行,相当于先执行程序的主要逻辑,将耗时的操作推迟执行。

回调函数的优点是简单、容易理解和部署,缺点是不利于代码的阅读和维护,各个部分之间高度耦合,流程会很混乱,而且每个任务只能指定一个回调函数

3.promise

ES 6中原生提供了Promise对象,Promise对象代表了某个未来才会知道结果的事件(一般是一个异步操作),并且这个事件对外提供了统一的API,可供进一步处理。
使用Promise对象可以用同步操作的流程写法来表达异步操作,避免了层层嵌套的异步回调,代码也更加清晰易懂,方便维护。

4.async函数

ES2017 标准引入了 async 函数,使得异步操作变得更加方便。async 函数是什么?一句话,它就是 Generator 函数的语法糖

详细内容直接看这里:http://es6.ruanyifeng.com/#docs/async

六、函数相关

1.函数参数默认值(函数默认参数)

 // ES6 允许为函数的参数设置默认值,即直接写在参数定义的后面:
function log(x, y = 'World') {
console.log(x, y);
} log('Hello') // Hello World
log('Hello', 'China') // Hello China
log('Hello', '') // Hello

2.箭头函数

箭头函数就是匿名函数定义的简化版, 宣称能使得代码更简洁,实际上就是纯粹的垃圾
箭头函数的 this 值是绑定了的,箭头函数没有 arguments 对象,如果要多参数, 必须用 ...

语法如下:

 // (参数1, 参数2) => { 语句 }
// (参数1, 参数2) => 语句
// 上面两行相当于下面这函数
function(参数1, 参数2) {
return 语句
} // 如果只有一个参数,圆括号可省略的
// (参数1) => { 语句 }
// 参数1 => { 语句 } // 但是如果没有参数, 必须需要使用圆括号
// () => { 语句 } // 例子
var a1 = [1, 2, 3]
// 下面两个等价
var a2 = a1.map(function(n){
return n * n
})
var a3 = a1.map( n => n * n ) n => n * n
// 上面 1 行等价于下面 3 行
function(n) {
return n * n
}

了解ES6的更多相关文章

  1. ES6模块import细节

    写在前面,目前浏览器对ES6的import支持还不是很好,需要用bable转译. ES6引入外部模块分两种情况: 1.导入外部的变量或函数等: import {firstName, lastName, ...

  2. webpack+react+redux+es6开发模式

    一.预备知识 node, npm, react, redux, es6, webpack 二.学习资源 ECMAScript 6入门 React和Redux的连接react-redux Redux 入 ...

  3. ES6的一些常用特性

    由于公司的前端业务全部基于ES6开发,于是给自己开个小灶补补ES6的一些常用特性.原来打算花两天学习ES6的,结果花了3天才勉强过了一遍阮老师的ES6标准入门(水好深,ES6没学好ES7又来了...) ...

  4. ES6(块级作用域)

    我们都知道在javascript里是没有块级作用域的,而ES6添加了块级作用域,块级作用域能带来什么好处呢?为什么会添加这个功能呢?那就得了解ES5没有块级作用域时出现了哪些问题. ES5在没有块级作 ...

  5. es6小白学习笔记(一)

    1.let和const命令 1.es6新增了let和const命令,与var用法类似,但它声明的变量只在let所在的代码块内有效(块级作用域,es5只有全局和函数作用域) { let a = 1; v ...

  6. ES6之变量常量字符串数值

    ECMAScript 6 是 JavaScript 语言的最新一代标准,当前标准已于 2015 年 6 月正式发布,故又称 ECMAScript 2015. ES6对数据类型进行了一些扩展 在js中使 ...

  7. ES6之let命令详解

    let与块级作用域 { var foo='foo'; let bar='bar'; } console.log(foo,'var'); //foo varconsole.log(bar ,'bar') ...

  8. ES6 箭头函数中的 this?你可能想多了(翻译)

    箭头函数=>无疑是ES6中最受关注的一个新特性了,通过它可以简写 function 函数表达式,你也可以在各种提及箭头函数的地方看到这样的观点——“=> 就是一个新的 function”. ...

  9. ES6+ 现在就用系列(二):let 命令

    系列目录 ES6+ 现在就用系列(一):为什么使用ES6+ ES6+ 现在就用系列(二):let 命令 ES6+ 现在就用系列(三):const 命令 ES6+ 现在就用系列(四):箭头函数 => ...

  10. ES6+ 现在就用系列(一):为什么使用ES6+

    系列目录 ES6+ 现在就用系列(一):为什么使用ES6+ ES6+ 现在就用系列(二):let 命令 ES6+ 现在就用系列(三):const 命令 ES6+ 现在就用系列(四):箭头函数 => ...

随机推荐

  1. ODBC的基础架构

    *) 基本概念:1. 应用程序(Application)2. ODBC驱动管理器(ODBC Driver Manager) 负责管理应用程序和驱动程序间的通信,主要功能包括:解析DSN (数据源名称, ...

  2. java设计模——反射的应用 (利用反射来去除if判断语句)

    利用反射来去除if判断语句 我的以前写的一个查分系统,就是部长让我写的那个,使用一个分发器(函数),他会根据传递进来的字符串参数调用不同的方. If(“add”.equalsIgnoreCase(fu ...

  3. Ubuntu 18.10安装Firefox 和 Google Chrome

    ================================ 工作环境迁移到Linux上,操作系统使用Linux Mint19.1(基于Ubuntu的), 自带的浏览器器是低版本的英文版,现在使用 ...

  4. ACM常用算法

    数据结构 栈,队列,链表 哈希表,哈希数组 堆,优先队列 双端队列 可并堆 左偏堆 二叉查找树 Treap 伸展树 并查集 集合计数问题 二分图的识别 平衡二叉树 二叉排序树 线段树 一维线段树 二维 ...

  5. laravel记住登录、设置时间

    laravel 自动登陆的时间改如何实现? 控制器 public function login(){ $email =Input::get('email');$password  = Input::g ...

  6. MySQL Transaction--RR事务隔离级别下加锁测试

    ============================================================================== 按照非索引列更新 在可重复读的事务隔离级别 ...

  7. solrcloud配置中文分词器ik

    无论是solr还是luncene,都对中文分词不太好,所以我们一般索引中文的话需要使用ik中文分词器. 三台机器(192.168.1.236,192.168.1.237,192.168.1.238)已 ...

  8. ballerina 学习 三十二 编写安全的程序

      ballerina编译器已经集成了部分安全检测,在编译时可以帮助我们生成错误提示,同时ballerina 标准库 已经对于常见漏洞高发的地方做了很好的处理,当我们编写了有安全隐患的代码,编译器就已 ...

  9. 变量延迟(setlocal)之浅见

    变量延迟,浅见认为就是变量预处理,在事先声明变量,告诉cmd环境哪个先哪个后.默认情况下是停用,可以用两种方法启用/停用: 一.cmd /v:on 和cmd /v:off ,范围在cmd这个环境直至e ...

  10. Java HashMap原理

    HashMap存储结构 HashMap中数据的存储是由数组与链表一起实现的 数组寻址非常容易,其时间复杂度为O(1),但是当要插入或删除数据时,时间复杂度就会变为O(n).链表插入和删除操作的内存复杂 ...