ECMAScript 8都发布了,你用的是什么版本?
什么是ES6?ES6就是ECMAScript6,是新版本的JavaScript语言标准。其实ECMAScript 6.0早在2015年6月正式发布了,它是新版本的 JavaScript 语言标准,主要是使用JavaScript 语言来为企业级编写复杂的大型应用程序,是一种开发语言。目前大多数环境及框架都支持ES6标准。
ES6和ES5相比,它给开发人员带来了很多新的特性。它的语法相较于其他版本而言会更加的简洁规范,但是在功能上更加强大,可以简单的实现复杂的操作。除此以外,ES6的应用,让前后语法更加统一,差异大大缩小,大大提升开发效率,提高了代码的安全性。
在ES6中以下是一些比较常用的特性,例如:Classes(类)、Modules(模块)、Default Parameters(默认参数)、Arrow Functions (箭头函数)、Multi-line Strings (多行字符串)、Template Literals (模板字符串)、Enhanced Object Literals (增强的对象文本)、Destructuring Assignment (解构赋值)、Block-Scoped Constructs Let and Const(块作用域构造Let and Const)以及Promises等。
以下就是对常用的ES6特性的介绍。
其实在ES6中,需要声明变量的关键字除了var和function还新增加了let、const、class和import。 其中let和const要和块级作用域结合才能发挥其优势。
那什么是块级作用域?块级作用域的表示任何一对大括号{}包围的语句集都是一个块,而在这个作用域里面定义的所有变量在代码块外都是不可访问的,所以是块级作用域。当然,在块级作用域中还可以声明函数,该函数也是只能作用域内部才能被访问到。块级作用域可以避免内层变量覆盖外层变量可以更好的来管理变量。
在ES6之前,javascript中没有块级作用域的概念,也就是说,JS并不支持块级作用域,它只支持函数作用域,而且只有全局作用域和函数作用域两种。在javascript使用函数作用域时,就表明变量在声明它们的函数时,所有变量在函数体内始终是可见的,有定义的。这样就意味着变量在声明之前就可以使用,这个特性被称为“声明提前”,即javascript函数里用var或者function声明的所有变量或者函数会被提前到作用域的顶部。
在使用let声明的变量时,只在它所在的块级作用域内有效代码块内有效。 let不允许在相同作用域内,重复声明同一个变量,不能跨块访问,也不能跨函数访问。而var定义的变量,没有块的概念,可以跨块访问 ,且声明会被提前。var命令会发生变量提升现象,也就是说变量可以在声明之前使用。但有一点需要注意,在let声明变量前,使用该变量语句,会报错该变量未被声明。如以下例子在最新版本的Chrome浏览器的控制台(支持一部分ES6语法)执行就会报错。
{
var hello = 'Hello'
let world = 'World'
}
console.log(hello);
console.log(world);
let与constconst声明使用基本相同,同样是存在于块级作用域内。最大不同点就是:const声明一个只读的常量。一旦声明,常量的值就不能改变,而且必须同时给常量初始化赋值,不然会报错。
而在ES6中,除了增加了let和const两种声明方式,还有接下来要介绍的import和class的声明方式。
Default Parameters(默认参数)是ES6中对函数拓展的一个特性,可以直接为函数的参数设置默认值,当某一参数设置了默认值时,如果调用函数的时候没有传该参数,则该参数的值为默认值,如果传了该参数,则该参数的值为传递的参数值。
在ES6之前,函数的参数设置默认值都是通过手动的方式设置,代码如下:
function sign (x) {
if (typeof x === 'undefined') {
x = 'default'
}
console.log(x)
}
sign('new sign') // new sign
sign() // default
如果将上述代码换成ES6模式,如下:
function sign (x = 'default') {
console.log(x)
}
sign('new sign') // new sign
sign() // default
通过对比可以看出,ES6把默认值部分从大括号移到了小括号里,还减少了运算,这样看上去更加简洁明了。
在ES6中,Enhanced Object Literals (增强的对象文本)对象字面值扩展支持在创建时设置原型,简写foo:foo分配,定义方法是通过加工父函数(super calls),计算属性名(动态)。
var obj = {
// __proto__ 原型
__proto__: theProtoObj,
// Shorthand for ‘handler: handler’ 简写
handler,
// Methods
toString() {
// Super calls 继承
return "d " + super.toString();
},
// Computed (dynamic) property names 计算属性名
['prop_' + (() => 42)()]: 'name'
};
在ES6中Template Literals (模板字符串)是使用反引号 (` `) 和${ }来代替普通字符串中的用双引号和单引号,实现字符串的拼接,字符串中可以嵌入变量。
但是在ES6之前,我们的输出代码一般是:
var name = 'Henry'
var welcome = 'Hello, ' + name + '!'
console.log(welcome); // Hello, Henry!
在ES6中,模板字符串可以这样拼接字符串:let name = 'Henry'
let welcome = `Hello, ${ name }!`;
console.log(welcome); // Hello, Henry
模板字符串的计算原则是在两个反引号之间将字符串拼接到一起,如果反引号之间含有${ },则会计算这对大括号内的值,大括号里面可以是任意的JavaScript表达式,可以进行运算和引用对象属性。代码如下:
let a = 3;
let number = `$ {a + 2 }`;
console.log(`${ number }`); // 5
let b = { c: 2, d: 4 };
console.log(`${ b.c * b.d }`) ; // 8
Multi-line Strings (多行字符串)跟Template Literals (模板字符串)是同样的解析方式,它是模板字符串的拓展,但是它可以拼接多行的字符串,且拼接的字符串中会保留所有的空格和缩进。
如果需要用字符串来拼接DOM树结构时,可以这样写:
let titleValue = 'This is a title';
let htmlStr = `
可以从以上代码看出它们是JavaScript和伪html代码的结合,它可以将模板字符串的多行字符串封装成一个页面模板工具。这种书写方式跟JSX非常相似。
在ES6中是允许使用“箭头”( => )定义函数,称作Arrow Functions (箭头函数)。(=> 前面的部分是函数的参数,=> 后面的部分是函数的代码块。)
在ES5中声明一个函数,代码如下:
var func = function (a) {
return a + 2;
}
但是若将这个函数换成箭头函数,代码如下:
let func = a => a + 2;
如果箭头函数有多个参数,需要用括号将它们括起来,只有一个参数的时候,可以省略括号,如果没有设置参数,也必须有括号。示代码如下:
let func1 = (arg1, arg2, arg3) => {
return arg1 + arg2 + arg3;
}
let func2 = arg => {
console.log(arg)
}
let func3 = () => {
console.log(`This is an arrow function.`)
}
需要注意的是,箭头函数内部没有自己的this,如果在箭头函数内部使用this,那样这个this是箭头函数外部的this,也是因为箭头函数没有this,这样就会导致内部的this 就是外层代码块的 this。所以,箭头函数不能用作构造函数。如果用箭头函数来写回调函数时,就不用再将外部this保存起来了。
箭头函数的代码如下:
// ES6
function foo() {
setTimeout(() => {
console.log(`id:${ this.id }`)
}, 100)
}
// ES5
function foo() {
var _this = this;
setTimeout(function() {
console.log('id:', _this.id);
}, 100)
}
Promise是异步编程的一种解决方案,它是一个对象,它的状态不受外界影响且只要开始就会一直进行下去,直到成功或者失败,也可以从它可以获取异步操作的消息。就像一个容器一样,一旦状态改变就不会再变,任何时候都是这种结果。
Promise的结果是由异步操作的结果决定的,且一旦结果形成,便不可再被改变,任何时候都得到同样的结果。但需要注意的是Promise对象中的状态一旦被确定为成功或者失败,无法被取消,会执行下去,直到出现结果,如果不设置回调,那内部抛出的异常,是不会被反应到外部的。