ES6 的新特性 - 让前后端差异越来越小
ES6(ECMAScript 6)是即将到来的新版本 JavaScript 语言的标准,代号 harmony(和谐之意,显然没有跟上我国的步伐,我们已经进入中国梦版本了)。上一次标准的制订还是 2009 年出台的 ES5。目前 ES6 的标准化工作正在进行中,预计会在 14 年 12 月份放出正式敲定的版本。但大部分标准已经就绪,且各浏览器对 ES6 的支持也正在实现中。
潮流虽然太快,但我们不停下学习的步伐,就不会被潮流丢下的,下面来领略下 ES6 中新特性,一堵新生代 JS 的风采。
1、箭头操作符
如果你会 C# 或者 Java,你肯定知道 lambda 表达式,ES6 中新增的箭头操作符 => 便有异曲同工之妙。它简化了函数的书写。操作符左边为输入的参数,而右边则是进行的操作以及返回的值 Inputs=>outputs。
我们知道在 JS 中回调是经常的事,而一般回调又以匿名函数的形式出现,每次都需要写一个 function,甚是繁琐。当引入箭头操作符后可以方便地写回调了。请看下面的例子。 var array = [1, 2, 3];
//传统写法
array.forEach(function(v, i, a) {
console.log(v);
});
//ES6
array.forEach(v = > console.log(v));
2、类的支持
ES6 中添加了对类的支持,引入了 class 关键字(其实 class 在 JavaScript 中一直是保留字,目的就是考虑到可能在以后的新版本中会用到,现在终于派上用场了)。JS 本身就是面向对象的,ES6 中提供的类实际上只是 JS 原型模式的包装。现在提供原生的 class 支持后,对象的创建,继承更加直观了,并且父类方法的调用,实例化,静态方法和构造函数等概念都更加形象化。
下面代码展示了类在 ES6 中的使用
//类的定义
class Animal {
//ES6中新型构造器
constructor(name) {
this.name = name;
}
//实例方法
sayName() {
console.log(‘My name is ‘+this.name);
}
}
//类的继承
class Programmer extends Animal {
constructor(name) {
//直接调用父类构造器进行初始化
super(name);
}
program() {
console.log("I‘m coding...");
}
}
//测试我们的类
var animal=new Animal(‘dummy‘),
wayou=new Programmer(‘wayou‘);
animal.sayName();//输出 ‘My name is dummy’
wayou.sayName();//输出 ‘My name is wayou’
wayou.program();//输出 ‘I‘m coding...’
3、增强的对象字面量
对象字面量被增强了,写法更加简洁与灵活,同时在定义对象的时候能够做的事情更多了。具体表现在:
- 可以在对象字面量里面定义原型
- 定义方法可以不用 function 关键字
- 直接调用父类方法
这样一来,对象字面量与前面提到的类概念更加吻合,在编写面向对象的 JavaScript 时更加轻松方便了。
//通过对象字面量创建对象
var human = {
breathe() {
console.log(‘breathing...‘);
}
};
var worker = {
__proto__: human, //设置此对象的原型为human,相当于继承human
company: ‘freelancer‘,
work() {
console.log(‘working...‘);
}
};
human.breathe();//输出 ‘breathing...’
//调用继承来的breathe方法
worker.breathe();//输出 ‘breathing...’
4、字符串模板
字符串模板相对简单易懂些。ES6 中允许使用反引号 ` 来创建字符串,此种方法创建的字符串里面可以包含由美元符号加花括号包裹的变量 ${vraible}。如果你使用过像 C# 等后端强类型语言的话,对此功能应该不会陌生。
//产生一个随机数
var num=Math.random();
//将这个数字输出到console
console.log(`your num is ${num}`);
5、解构
自动解析数组或对象中的值。比如若一个函数要返回多个值,常规的做法是返回一个对象,将每个值做为这个对象的属性返回。但在 ES6 中,利用解构这一特性,可以直接返回一个数组,然后数组中的值会自动被解析到对应接收该值的变量中。
var [x,y]=getVal(),//函数返回值的解构
[name,,age]=[‘wayou‘,‘male‘,‘secrect‘];//数组解构
function getVal() {
return [ 1, 2 ];
}
console.log(‘x:‘+x+‘, y:‘+y);//输出:x:1, y:2
console.log(‘name:‘+name+‘, age:‘+age);//输出: name:wayou, age:secrect
6、let 与 const 关键字
可以把 let 看成 var,只是它定义的变量被限定在了特定范围内才能使用,而离开这个范围则无效。const 则很直观,用来定义常量,即无法被更改值的变量
for (let i=0;i<2;i++)console.log(i);//输出: 0,1
console.log(i);//输出:undefined,严格模式下会报错
7、for of 值遍历
我们都知道 for in 循环用于遍历数组,类数组或对象,ES6 中新引入的 for of 循环功能相似,不同的是每次循环它提供的不是序号而是值。
var someArray = [ "a", "b", "c" ];
for (v of someArray) {
console.log(v);//输出 a,b,c
}
8、模块
在 ES6 标准中,JavaScript 原生支持 module 了。这种将 JS 代码分割成不同功能的小块进行模块化的概念是在一些三方规范中流行起来的,比如 CommonJS 和 AMD 模式。
将不同功能的代码分别写在不同文件中,各模块只需导出公共接口部分,然后通过模块的导入的方式可以在其他地方使用。
// point.js
module "point" {
export class Point {
constructor (x, y) {
public x = x;
public y = y;
}
}
}
// myapp.js
//声明引用的模块
module point from "/point.js";
//这里可以看出,尽管声明了引用的模块,还是可以通过指定需要的部分进行导入
import Point from "point";
var origin = new Point(0, 0);
console.log(origin);
9、Map,Set 和 WeakMap,WeakSet
这些是新加的集合类型,提供了更加方便的获取属性值的方法,不用像以前一样用 hasOwnProperty 来检查某个属性是属于原型链上的呢还是当前对象的。同时,在进行属性值添加与获取时有专门的 get,set 方法
// Sets
var s = new Set();
s.add("hello").add("goodbye").add("hello");
s.size === 2;
s.has("hello") === true;
// Maps
var m = new Map();
m.set("hello", 42);
m.set(s, 34);
m.get(s) == 34;
有时候我们会把对象作为一个对象的键用来存放属性值,普通集合类型比如简单对象会阻止垃圾回收器对这些作为属性键存在的对象的回收,有造成内存泄漏的危险。而 WeakMap,WeakSet 则更加安全些,这些作为属性键的对象如果没有别的变量在引用它们,则会被回收释放掉,具体还看下面的例子
// Weak Maps
var wm = new WeakMap();
wm.set(s, { extra: 42 });
wm.size === undefined
// Weak Sets
var ws = new WeakSet();
ws.add({ data: 42 });//因为添加到ws的这个临时对象没有其他变量引用它,所以ws不会保存它的值,也就是说这次添加其实没有意思
10、Symbols
我们知道对象其实是键值对的集合,而键通常来说是字符串。而现在除了字符串外,我们还可以用 symbol 这种值来做为对象的键。Symbol 是一种基本类型,像数字,字符串还有布尔一样,它不是一个对象。Symbol 通过调用 symbol 函数产生,它接收一个可选的名字参数,该函数返回的 symbol 是唯一的。之后就可以用这个返回值做为对象的键了。Symbol 还可以用来创建私有属性,外部无法直接访问由 symbol 做为键的属性值。
(function() {
// 创建symbol
var key = Symbol("key");
function MyClass(privateData) {
this[key] = privateData;
}
MyClass.prototype = {
doStuff: function() {
... this[key] ...
}
};
})();
var c = new MyClass("hello")
c["key"] === undefined//无法访问该属性,因为是私有的
11、Math,Number,String,Object 的新 API
对 Math,Number,String 还有 Object 等添加了许多新的 API。下面代码同样来自 es6features,对这些新 API 进行了简单展示。
Number.EPSILON
Number.isInteger(Infinity) // false
Number.isNaN("NaN") // false
Math.acosh(3) // 1.762747174039086
Math.hypot(3, 4) // 5
Math.imul(Math.pow(2, 32) - 1, Math.pow(2, 32) - 2) // 2
"abcde".contains("cd") // true
"abc".repeat(3) // "abcabcabc"
Array.from(document.querySelectorAll(‘*‘)) // Returns a real Array
Array.of(1, 2, 3) // Similar to new Array(...), but without special one-arg behavior
[0, 0, 0].fill(7, 1) // [0,7,7]
[1,2,3].findIndex(x => x == 2) // 1
["a", "b", "c"].entries() // iterator [0, "a"], [1,"b"], [2,"c"]
["a", "b", "c"].keys()