ECMAScript6入门(一)
ECMAScript6入门(一)
这篇博客将会带你入门ECMAScript 6(ES6):
1.解释了如何以交互方式使用ES6。
2.列出了易于采用的ES6特性,以及这些特性在ES5中的编码方式。
尝试ECMAScript6
三种简单的使用ES6的方法:
- Web 浏览器:使用在线BabelRepl:一个将ES5编译为ES6的交互之地。这个选项不需要安装任何东西;
- 命令行:使用babel-node,它是Node.js可执行文件的一个版本,可以识别ES6(并在内部编译为ES5)。可通过npm安装;
- 各种javascript引擎:检查kangax的ES6兼容性表去找出本地支持哪些ES6的功能;
接下来详细介绍方法一和方法二。
1.1 Babel RePL
Bebel REPL有四个主要部分。
1)左上方的窗口包含ES6源代码。
2)左下窗口显示在ES6代码中发现的语法错误。
3)右上方窗口包含ES6代码编译到的ES5代码。
4)右下方窗口显示通过console.log()的输出。
1.2 babel-node
可以通过npm安装babel-node可执行文件:
$ npm install --global babel
你可以像使用Node.js可执行node那样使用它。与node类似,交互式REPL的启动方式如下:
$ babel-node
一旦在该repl中,就可以执行ES6代码:
let arr = [1, 2, 3];
arr.map(x => x * x)
[ 1, 4, 9 ]
注意:babel-node暂时不支持多行输入。
Babel 官网有更多[有关Babel CLI的工具(https://babeljs.io/docs/en/babel-cli/)]
本文的其余部分描述了易于采用的ES6特性。
从 var 到 let/const
ES6有两种新的方式去声明变量:
1)let是var的一个block-scoped版本
2)const就像let,但是它创建的常量和变量的值是不能被改变的。
通常可以用let或者const代替每个var,但是不能盲目使用,因为不同类型的作用域可以改变代码的行为方式。作为一个例子,来看看下面这个ES5代码:
var x = 3;
function func(randomize) {
if (randomize) {
var x = Math.random(); // (A) scope: whole function
return x;
}
return x; // accesses the x from line A
}
func(false); // undefined
func()函数返回undefined可能会很让人惊讶。你可以知道为什么你重写以至于它更能清晰地反应实际发生了什么。
var x = 3;
function func(randomize) {
var x;
if (randomize) {
x = Math.random();
return x;
}
return x;
}
func(false); // undefined
如果在初始版本用let替换var,会得到不同的结果:
let x = 3;
function func(randomize) {
if (randomize) {
let x = Math.random();
return x;
}
return x;
}
func(false); // 3
因此,盲目地用let替换var或者const是很危险的,我的建议是:
·只在新的ES6代码中使用
·保留原来的代码,或者仔细地重构它。
从IIFEs到blocks
在ES5中,如果要保持变量局部,则必须使用IIFE(自执行匿名函数):
(function () { // open IIFE
var tmp = ···;
···
}()); // close IIFE
console.log(tmp); // ReferenceError
在EcmaScript 6中,您可以简单地使用block(语句块)和let声明:
{ // open block
let tmp = ···;
···
} // close block
console.log(tmp); // ReferenceError
更多信息:“Exploring ES6”中的“ES6中避免IIEFs”
从连接字符串到模板文本
使用ES6,javascript最终获得字符串插值和多行字符串的文本。
字符串差值
在ES5中,通过连接这些值和字符串片段将值放入字符串中:
function printCoord(x, y) {
console.log(’(’+x+’, ‘+y+’)’);
}
在ES6中,可以通过模板文本使用字符串插值:
function printCoord(x, y) {
console.log((${x}, ${y})
);
}
多行字符串
模板文本还有助于表示多行字符串。
例如,要在ES5中表示一个多行字符串,您必须这样做:
var HTML5_SKELETON =
‘<!doctype html>\n’ +
‘< html>\n’ +
‘< head>\n’ +
’ < meta charset=“UTF-8”>\n’ +
’ < title></ title>\n’ +
‘< /head>\n’ +
‘< body>\n’ +
‘< /body>\n’ +
‘< /html>\n’;
如果您通过反斜杠转义换行符,看起来会更好一点(但是您仍然需要显式地添加换行符):
var HTML5_SKELETON = ’
<!doctype html>\n
< html>\n
< head>\n
< meta charset=“UTF-8”>\n
< title></title>\n
< /head>\n
< body>\n
< /body>\n
</ html>’;
ES6模板文本可以跨多行:
const HTML5_SKELETON = ’
<!doctype html>
< html>
< head>
< meta charset=“UTF-8”>
< title></title>
< /head>
< body>
< /body>
</ html>’;
(这些例子在有多少空白方面有所不同,但在本例中这并不重
要。)
从函数表达式到箭头函数
在ES5代码中,无论何时你在使用函数表达式的时候必须注意这一点。在下面的例子中,我创建了helper变量“this”(A行),以便可以在B行中访问uicomponent的this。
function UiComponent {
var _this = this; // (A)
var button = document.getElementById(‘myButton’);
button.addEventListener(‘click’, function () {
console.log(‘CLICK’);
_this.handleClick(); // (B)
});
}
UiComponent.prototype.handleClick = function () {
···
};
在ES6中,你可以使用箭头函数,它不会隐藏此内容(A行,如下):
class UiComponent {
constructor() {
let button = document.getElementById(‘myButton’);
button.addEventListener(‘click’, () => {
console.log(‘CLICK’);
this.handleClick(); // (A)
});
}
handleClick() {
···
}
}
对于只返回表达式结果的短回调,箭头函数特别方便。
在ES5中,箭头函数相对冗长:
var arr = [1, 2, 3];
var squares = arr.map(function (x) { return x * x });
在ES6中,箭头函数更简洁:
let arr = [1, 2, 3];
let squares = arr.map(x => x * x);
当定义参数时,你甚至可以省略括号如果参数只是一个标识符。因此(X) => x * x 和 x => x * x 都可以。
处理多个返回值
一些函数或者方法通过数组或者对象返回多个值。在ES5中,如果要访问这些值,始终需要创建中间变量。在ES6中,你可以通过销毁避免中间变量。
通过数组返回多个值
exec()通过类似数组的对象返回捕获的组。在ES5中,你需要一个中间变量(下面例子中的matchObj),尽管你只对组感兴趣。
var matchObj =
/^(\d\d\d\d)-(\d\d)-(\d\d)$/
.exec(‘2999-12-31’);
var year = matchObj[1];
var month = matchObj[2];
var day = matchObj[3];
在ES6中,销毁使代码更加简洁:
let [, year, month, day] =
/^(\d\d\d\d)-(\d\d)-(\d\d)$/
.exec(‘2999-12-31’);
数组模式开头的空跳过了索引0处的数组元素。
通过类返回多个值
方法Object.getOwnPropertyDescriptor()返回了属性描述符,该对象在其属性中包含多个值。
在ES5中,尽管你只对一个对象的属性感兴趣,你仍需要一个中间变量(下面例子中的propDesc):
var obj = { foo: 123 };
var propDesc = Object.getOwnPropertyDescriptor(obj, ‘foo’);
var writable = propDesc.writable;
var configurable = propDesc.configurable;
console.log(writable, configurable); // true true
在ES6中,你可以用销毁:
let obj = { foo: 123 };
let {writable, configurable} =
Object.getOwnPropertyDescriptor(obj, ‘foo’);
console.log(writable, configurable); // true true
{writable, configurable} is an abbreviation for:
{ writable: writable, configurable: configurable }