ECMAScript 6入门

预计在2014年底,ECMAScript 6将会正式发布,他的草案在13年3月份被冻结,后续提出新特性将会移至ECMASript
7中。目前还没有哪款浏览器实现了ES6的全部内容,兼容性最强的一款要数FireFox了。具体情况可以在这里查看。

关于 ECMAScript 6 草案,我在博客里头复制了一份,可以点击这里

JavaScript的内容是越来越丰富,在ES6中还添加了模块(module)和类(class),感觉他已经失去了曾经的单纯了,不知道这些新功能的补充对开发者来说是福音还是负担。之前写过两篇关于ES6的文章,ECMAScript 6
简介
ECMAScript
6中的let和const关键词
,本文将一一介绍ES6中的一些新特性。

本文地址:http://www.cnblogs.com/hustskyking/p/ecmascript6-overview.html,转载请注明源地址。

注意:如果想测试以下属性,请安装 0.11+ 版本的 node,并添加上 --harmony 参数。

一、let 和 const

这个内容在 ECMAScript
6中的let和const关键词
 一文中已经介绍过了。简单来说就是一句话:ES6中引入了块级作用域,let的有效区间是他所在的
{} 大括号中。const 为常量,定义之后不能更改,也删除不了。

> const PI = 3.14;
> Object.getOwnPropertyDescriptor(window, PI)
Object {value: 3.1415, writable: false, enumerable: true, configurable: false}

writable 和 configurable 都是 false。

二、多变量的模式赋值

写过 coffee-script 的人都知道,我们可以这样给一个数据赋值:

num[1..3] = ["hello", "i‘am", "Barret Lee"]

ES6中也允许类似的多变量赋值:

var [x, y, z] = ["hello", "i‘am", "Barret Lee"];

更强大的是,他还适合对象:

var { foo, bar } = { foo: "Barret", bar: "Lee" };

这种赋值方式是模式匹配的,只要左侧跟右侧对应,便可以成功赋值。感觉新手不会太适应这种写法。

三、数组推导

先看例子:

var a1 = [1, 2, 3, 4];
var a2 = [i * 2 for (i of a1)];

a2 // [2, 4, 6, 8]

这东西只是简化了编程,没有从根本上增加功能和特性,写 coffee 的人应该比较喜欢,我看着还是有点不习惯,其实上面的写法就等价于:

var a1 = [1, 2, 3, 4];
var a2 = a1.map(function (i) { return i * 2 });

我想除非是代码长度有限制,否则这玩意儿正式出来了我也不会用它。

四、字符串的扩展

这一块的内容相当于是给 JS 编码打一个补丁,这个补丁用来弥补双字节 UTF-16
字符带来的问题,引入的各个函数也只是对不同场景的修复。这个扩展还是相当重要的,尤其是 ArrayBuffer 中数据类型的相关处理,涉及到很多类似
Float64Array Uint32Array 等类型化数组的处理,我在 你所不知道的JavaScript数组
曾提到过。

1. codePointAt

这个地方需要解释下 JavaScript 对字符的储存模式,JavaScript 中的字符串是以 UTF-16 为代码单元,通常我们使用的字符范围都在
Unicode 值 0x10000 以内,他们对应的 UTF-16 就是它们自身,但 Unicode 中也存在这个范围之外的字符,这时候就需要两个 UTF-16
字符来描述,比如:

alert("??".length); //2

因为字符串的 length 表示的并不是字符个数,而是 UTF-16 的单元个数。关于这方面知识的具体介绍,可以戳这里

ES6提供了 codePointAt 函数来正确处理 4 个字节储存的字符。

var s = "??二";
s.codePointAt(0);

codePointAt 会把 s 中的两个字符都正确解析出来,相当于智能的将储存单元切换为 2 或者 4.

2. fromCodePoint

对应 String.fromCharCode 的能够智能解析 s 的函数是 String.fromCodePoint

3. 字符的Unicode表示法

我们知道可以使用 \u0000-\uFFFF 来表示一个 Unicode 字符,依然是上面的问题,如果字符超出了这个范围,比如 "\u10000"
这个字符,便不能正确的解析出来,ES6中可以这样:

#\u{10000}

用大括号括起来就可以正常解析超过 FFFF 的字符了。

4. 正则修饰符 u

/^.$/.test("??") // false
/^..$/.test("??") // true
/^.$/u.test("??") // true

看到上面三个测试,相信你已经知道是什么意思了。

5. 几个没啥意思的函数

contains(), startsWith(), endsWith(), repeat()

都是对 String 的拓展,顾名就能思意。

6. 模板字符串

之前写过一篇关于 TEMPLATE 标签的文章,这里我们又看到了一个跟模板相关的东西。


// 字符串中嵌入变量
var name = "Bob", time = "today";
`Hello ${name}, how are you ${time}?`

var x = 1;
var y = 2;
console.log(`${ x } + ${ y } = ${ x + y}`)
// "1 + 2 = 3"

配合 TEMPLATE 标签使用是比较方便的,不过 TEMPLATE 标签可以很方便的使用自定义标签,这个特性也不是很突出了。


<div id="test">
<x-from>DOM文档</x-from>
<x-name>test元素</x-name>
</div>

<template id="temp">
我是来自 <strong><content select="x-from"></content></strong>
中的 <strong><content select="x-name"></content></strong>
的数据。
</template>

<script>
var root = test.webkitCreateShadowRoot();
root.appendChild(document.importNode(temp.content));
</script>

五、数值的扩展


1. 二进制和八进制表示法

0b111110111 === 503 // true
0o767 === 503 // true

前缀 0b 和 0o 表示二进制和八进制数值

2. 扩展函数


  • Number.isFinite()

  • Number.isNaN()

  • Number.parseInt()

  • Number.parseFloat()

  • Number.isInteger()

具体细节可以去 MDN
上搜查。

六、对象的扩展

在 ES5.1 中我们看到了 Object 的灵活性提高了很多,加入了 create、defineProperty、freeze
等等很多十分有用的方法,而在 ES6 中,依然继续加强:

1. Object.is()

比较严格相等,传入两个参数,其功能跟 === 差不多,不同的是:+0不等于-0,NaN与本身恒等

+0 === -0 //true
NaN === NaN // false

Object.is(+0, -0) // false
Object.is(NaN, NaN) // true

2. proto属性

obj.__proto__ = otherObj;

这东西浏览器早就实现了,只是在 ES6 才被纳入标准中,还记得这东西被用来判断是否为 IE 么:

var isIE = "__proto__" in {} ? false : true;

3. 增强的对象写法

又是一个装饰品:


var Person = {
name: ‘Barret Lee‘,

//等同于birth: birth
birth,

// 等同于hello: function ()...
hello() { console.log(‘My Name Is‘, this.name); }

};

4. 允许变量渗入 key 中


var name = "my name";
var Me = {
[name]: "Barret Lee",
"name": "李靖"
};
Me[name] // "Barret Lee"
Me["my name"] // "Barret Lee"
Me["name"] // "李靖"

挺方便的,不过容易出错,比如上面,看晕了吧~

5. Symbol

一种从类型上区分数据的工具,他是一个原始类型的值,不是对象,很适合做标识符。

6. Proxy

Proxy 内置的一个代理工具,使用他可以在对象处理上加一层屏障:


var plain = {
name : "Barret Lee"
};
var proxy = new Proxy(plain, {
get: function(target, property) {
return property in target ? target[property] : "我擦";
}
});

proxy.name // "Barret Lee"
proxy.title // "我擦"

Proxy(target, handler), 这里的 handler 可以是 set get has hasOwn keys
等等方法,具体可以移步这里:http://wiki.ecmascript.org/doku.php?id=harmony:direct_proxies

七、函数的扩展


1. 参数设置默认值


function Point(x = 0, y = 0) {
this.x = x;
this.y = y;
}

var p = new Point();
// p = { x:0, y:0 }

他这个参数可以初始化相当于暴露更多的底层接口吧,提高了函数的拓展性。

2. rest运算符(...)


function add(...values) {
let sum = 0;

for (var val of values) {
sum += val;
}

return sum;
}
add(1, 2 ,3) // 6

这里的 values 需要用 val of values 来遍历。

3. 箭头函数(=>)

之前写过 coffee ,所以对这个我还是比较熟悉的:

var f = (a, b) => {return a + b};

这个跟上面提到的一些内容一样,都是装饰性的,没太多用途。

八、Set和Map数据结构


1. Set

简单点解释,他就是一个没有重复数值的数组。或者说他就是一个数组的 hash 表。

var items = new Set([1,2,3,4,5,5,5,5]);

for (i of s) {console.log(i)}
// 2 3 4 5

其遍历也是使用 val of values,他没有继承 Array 的方法,自己的几个方法是:

  • size():返回成员总数。

  • add(value):添加某个值。

  • delete(value):删除某个值。

  • has(value):返回一个布尔值,表示该值是否为set的成员。

  • clear():清除所有成员。

转化为数组的方式:

var items = new Set([1, 2, 3, 4, 5]);
var array = Array.from(items);

2. Map

Map 是一个“超对象”,其 key 除了可以是 String 类型之外,还可以为其他类型(如:对象)


var m = new Map();

o = {p: "Hello World"};

m.set(o, "content")

console.log(m.get(o))
// "content"

他的方法和 Set 差不多:

  • size:返回成员总数。

  • set(key, value):设置一个键值对。

  • get(key):读取一个键。

  • has(key):返回一个布尔值,表示某个键是否在Map数据结构中。

  • delete(key):删除某个键。

  • clear():清除所有成员。

  • keys():返回键名的遍历器。

  • values():返回键值的遍历器。

  • entries():返回所有成员的遍历器。

3. WeakMap

如果说Map 是一个“超对象”,那 WeakMap 就是个 “弱超对象”,他的键值只能是除 null 以外的对象。他的存在是为了方便垃圾回收。

八、遍历器(Iterator)

相比 Array,他对数据的管理更为紧凑,而且可操纵性也比较强,以后会成为一个比较通用的 JS 工具。


function idMaker(){
var index = 0;

return {
next: function(){
return {value: index++, done: false};
}
}
}

var it = idMaker();

it.next().value // ‘0‘
it.next().value // ‘1‘
it.next().value // ‘2‘

一个对象只要具备了next方法,就可以用for...of循环遍历它的值。

for (var n of it) {
if (n > 5)
break;
console.log(n);
}

九、Generator 函数

Generator就是一个改装了的 Iterator 遍历器,通过 yield 来增加一个 next() 节点。

声明一个 Generator 的方法:

function * foo( input ) {
var res = yield input;
}

使用方式:


function * foo( input ) {
var res = yield input;
}

var g = foo(10);
g.next(); // { value: 10, done: false }
g.next(); // { value: undefined, done: true }

Genrator的标识就是函数名前面有个 * 号,由于每个 yield 都会增加一个 next() 节点,当我们在一个
Generator 中添加多个 yield 的时候:


function* G() {
yield ‘Barret‘;
yield ‘Lee‘;
}

var g = G();
g.next(); // "Barret"
g.next(); // "Lee"
g.next(); // undefined
g.next(); // Error: Generator has already finished

相比 Iterator,我更喜欢 Generator。

十、Promise 对象

ES6将 Promise 纳入规范之后,很多浏览器根据 Promise/A+ 规范实现了一套 API,Promise对象是对异步操作的平坦式表达,避免了
callback hell,也就是多层嵌套的回调函数。这方面的东西可以参考我之前写的 JavaScript异步编程原理.

这里是 Promise/A+
规范文档,感兴趣的可以阅读一下。

在Promises/A规范中,每个任务都有三种状态:默认(pending)、完成(fulfilled)、失败(rejected)。

  • 默认状态可以单向转移到完成状态,这个过程叫resolve,对应的方法是deferred.resolve(promiseOrValue);

  • 默认状态还可以单向转移到失败状态,这个过程叫reject,对应的方法是deferred.reject(reason);

  • 默认状态时,还可以通过deferred.notify(update)来宣告任务执行信息,如执行进度;

  • 状态的转移是一次性的,一旦任务由初始的pending转为其他状态,就会进入到下一个任务的执行过程中。

十一、Class和Module


1. Class

Class,对象模板:


class Point {

constructor(x, y) {
this.x = x;
this.y = y;
}

toString() {
return ‘(‘+this.x+‘, ‘+this.y+‘)‘;
}

}

一下子就有了 C++/Java 的感觉了,在类中可以使用 extends 继承:


class ColorPoint extends Point {

constructor(x, y, color) {
super(x, y); // same as super.constructor(x, y)
this.color = color;
}

toString() {
return this.color+‘ ‘+super();
}

}

2. Module


之前在这篇文章谈过模块化编程的必要性,时代在变化,需求也在变,ES6引入
Module
也算是与时俱进。ES6允许将独立的js文件作为模块,也就是说,允许一个JavaScript脚本文件调用另一个脚本文件,从而使得模块化编程成为可能。


// circle.js

export function area(radius) {
return Math.PI * radius * radius;
}

export function circumference(radius) {
return 2 * Math.PI * radius;
}

如果我们要引入 circle.js 的函数,可以:


// main.js

import { area, circumference } from ‘circle‘;

console.log("圆面积:" + area(4));
console.log("圆周长:" + circumference(14));

如果要引入整个 circle 的内容:


// main.js

module circle from ‘circle‘;

console.log("圆面积:" + circle.area(4));
console.log("圆周长:" + circle.circumference(14));

模块之间的继承使用这条命令:

// other.js
export * from ‘circle‘;

这个东西,很好用,可惜了,纯洁的 JS,被糟蹋成啥样了=. =

十二、感谢

本文的书写逻辑参考阮一峰的总结,并参入了一些个人主观色彩,感谢前人栽树!

十三、参考资料


ECMAScript 6入门,布布扣,bubuko.com

时间: 2024-10-05 14:40:06

ECMAScript 6入门的相关文章

《ECMAScript 6 入门- 第三章 字符串的扩展》 —— 摘抄

1. codePointAT方法 JavaScript内部,字符以UTF-16的格式储存,每个字符固定为2个字节.对于那些需要 4个字节储存的字符(Unicode编号大于0xFFFF的字符),JavaScript会认为它们是两个字符.ES6提供了codePointAt方 法,能够正确处理4个字节储存的字符,返回一个字符的Unicode编号. codePointAt方法是测试一个字符由两个字节还是由四个字节组成的最简单方法. function is32Bit(c) { return c.codeP

《ECMAScript 6 入门- 第四章 数值的扩展》 —— 摘抄

1. 二进制和八进制表示法 ES6提供了二进制和八进制数值的新的写法,分别用前缀0b和0o表示. 0b111110111 === 503 // true 0o767 === 503 // true 八进制用0o前缀表示的方法,将要取代已经在ES5中被逐步淘汰的加前缀0的写法. 2. Number.isFinite(), Number.isNaN() ES6在Number对象上,新提供了Number.isFinite()和Number.isNaN()两个方法,用来检查Infinite和NaN这两个

《ECMAScript 6 入门- 第一章 lef和const命令》 —— 摘抄

1 . lef命令 ES6新增了let命令,用来声明变量.它的用法类似于var,let声明的变量,只在let命令所在的代码块内有效. { let a = 10; var b = 1; } a // ReferenceError: a is not defined. b //1 2.const命令 const也用来声明变量,但是声明的是常量.一旦声明,常量的值就不能改变. const PI = 3.1415; PI // 3.1415 PI = 3; PI // 3.1415 const PI =

《ECMAScript 6 入门- 第二章 变量的解构赋值》 —— 摘抄

1.数组的解构赋值 ES6允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构(Destructuring). 旧做法: var a = 1; var b = 2; var c = 3; ES6做法: var [a,b,c] = [1,2,3]; 上面代码表示,可以从数组中提取值,按照对应位置,对变量赋值. 本质上,这种写法属于“模式匹配”,只要等号两边的模式相同,左边的变量就会被赋予对应的值.下面是一些使用嵌套数组进行解构的例子. var [foo,[[bar],bad]] =

ES6箭头函数(节选自《ECMAScript 6 入门》)

基本用法 ES6 允许使用"箭头"(=>)定义函数. var f = v => v; 上面的箭头函数等同于: var f = function(v) { return v; }; 如果箭头函数不需要参数或需要多个参数,就使用一个圆括号代表参数部分. var f = () => 5; // 等同于 var f = function () { return 5 }; var sum = (num1, num2) => num1 + num2; // 等同于 var

ECMAScript 6 入门学习笔记(零)——开始

所有es6笔记都是我自己提出来的一些点,没有很详细的例子什么的,这个链接就是我看的教程,有需要的可以看看.(http://es6.ruanyifeng.com/#docs/intro) 1.ECMAScript 和 JavaScript 的关系 ECMAScript 和 JavaScript 的关系是,前者是后者的规格,后者是前者的一种实现. 2.ES6 与 ECMAScript 2015 的关系 ES6 既是一个历史名词,也是一个泛指,含义是5.1版以后的 JavaScript 的下一代标准,

ECMAScript 6 入门之新的数据类型Symbol

1.Symbol,一个每次创建都不一样的值 Symbol undefined null Boolean String Number Object let c=Symbol("这是一个Symbol"); let a=Symbol(); let b=Symbol(); console.log("a:",a); console.log("b:",b); console.log("c:",c);console.log(a===b);

ECMAScript 6 入门之变量的解构赋值

1.数组 1. var a=1,b=2,c=3; console.log("a:",a) console.log("b:",b) console.log("c:",c) var[q,w,e]=[4,5,6]; console.log("q:",q) console.log("w:",w) console.log("e:",e) 2. var[q,[w,e]]=[4,[5,6]]; con

推荐一本书:《ECMAScript 6入门》

本书力争覆盖ES6与ES5的所有不同之处,对涉及的语法知识给予详细介绍,并给出大量简洁易懂的示例代码. 本书为中级难度,适合已有一定JavaScript语言基础的读者,用来了解这门语言的最新发展:也可当作参考手册,查寻新增的语法点.