1.多行字符串
在ES5中,处理长字符串时往往采用这样的写法:
var content = '<div class="container">' +
'<div class="header"></div>' +
'<div class="body"></div>' +
'<div class="footer"></div>' +
'</div>'
而在ES6 提供了更好---多行字符串,示例:
var content = `<div class="container">
<div class="header"></div>
<div class="body"></div>
<div class="footer"></div>
</div>`
2.字符串模板
除了创建多行字符串之外,``符号还可以用于创建字符串模板,我们可以在字符串模板中输出变量,示例:
let hello = 'hello'
let helloWorld = `${hello} world`
console.log(helloWorld)
运行结果
3.块级作用域
在ES5中,我们可以使用var关键字来声明函数作用域的变量。但在循环和判断语句中,var关键字并不生成作用域,这意味着在这两者的代码块中声明的变量在代码块外依然可以访问到,示例:
for (var i = 0; i < 10; i++) {}
console.log(i)
运行结果
在ES6中,我们可以使用let关键字来声明块级作用域的变量,示例
for (let i = 0; i < 10; i++) {}
console.log(i)
运行结果
ReferenceError: i is not defined
除了let之外,我们还可以使用const关键字来声明块级作用域的变量,不过使用const声明的变量不可以修改。
4.默认参数
在ES5中,对函数形式设置默认值需要这样写:
var createShape = function (type, size, color) {
var type = type || 'circle'
var size = size || 20
var color = color || '#417b9f'
}
在ES6中则可以这么写:
let createShape = function (type = 'circle', size = 20, color = '#417b9f') {
}
5.对象字面量
使用ES5语法来声明一个引用外部变量或者包含方法的对象时,我们可以会这么写:
var msg = 'hello'
var object = {
msg: msg,
logMsg: function () {
console.log(this.msg)
}
}
在ES6中则简化了这一写法,当对象引用外部变量和定义方法时,可以不再使用键值对的形式,示例:
let msg = 'hello'
let object = {
msg,
logMsg () {
console.log(this.msg)
}
}
6.析构赋值
在ES5中,分解一个对象需要这样写:
var author = {name: 'revin', email: '509129@qq.com'}
var name = author.name
var email = author.email
ES6则提供了更便捷的方式,示例:
let author = { name: 'revin', email: '509129@qq.com' }
let { name, email } = author
let { name: username, email: contact } = author
console.log(username)
console.log(contact)
除了对象外,我们还可以对更多类型的变量使用析构语法,示例
// 数组
let counter = [ 1,2,3 ]
let [ one, two, three ] = counter
let {0: four, 1:five, 2:six } = [ 4, 5, 6 ]
// 字符串
let [ a, b, c ] = 'abc'
let { length: len } = 'abc'
console.log(len);
// 数值和布尔
let { toString: s1 } = 123
let { toString: s2 } = true
console.log(s1);
console.log(s2);
这一特性妙用无穷,除了为开发带来方便之外,还能使代码看起来十分高大上,当然也可能使代码变得异常难读。
7.箭头函数
在ES6中,任何需要匿名函数的地方,我们都可以使用箭头函数来替代。下面是在ES5中的几个使用匿名函数的示例代码:
// 监听事件
document.body.onclick = function () {}
// 回调函数
setTimeout(function () {}, 10)
// 对象方法
var foo = {
init: function () {}
}
// 变量声明
var hub = function () {}
使用箭头函数如下
// 监听事件
document.body.onclick = () => {}
// 回调函数
setTimeout(() => {}, 10)
// 对象方法
var foo = {
init: () => {}
}
// 变量声明
var hub = () => {}
foot.init()
与匿名函数不同的是,箭头函数并不会创建函数作用域,箭头函数中的this指向父级作用域,这在使用Vue进行开发时需要特别注意。
8.类和对象
先来看一个示例:
class People { // 使用class关键字来定义类
constructor (name) { // 构造器
this.country = 'China' // 静态变量
this.name = name
}
getName () { // 方法 getName
return this.name
}
getCountry () {
return this.country
}
}
class Author extends People { // 继承People类
constructor (name, email) {
super(name) // 调用超类的构造器
this.email = email
}
getEmail () {
return this.email
}
}
let p = new People('Join') // 实例化对象
console.log(p.getName())
console.log(p.getCountry())
let a = new Author('revin', '509129@qq.com')
console.log(a.getName())
console.log(a.getCountry())
console.log(a.getEmail())
在示例中定义了People 类,其拥有构造函数、country属性和name属性、getCountry方法和getName 方法;之后,又定义了Author类,Author继承于People,还为其拓展了email 和 getEmail 方法。
声明了People类的实例p对象和Author类的示例a对象,并调用了示例的方法,代码运行之后,控制台打印出:
Join
China
revin
China
509129@qq.com
9.模块化
在ES6之前,JS的模块有两大山头:一是基于AMD规范的requireJS;二是基于CMD规范seaJS,两者都是为了弥补JS没有模块化机制的缺陷而出现。
自从ES6诞生以来,JS也终于有了自己模块化机制。那么在ES6中,模块是如何导入导出的呢?
ES6 提供了export和import一对关键字进行模块导入和导出,示例:
greentings.js
// 导出常量
export const author = 'revin'
// 导出函数
export function sayHello(name) {
return `Hello ${name}`
}
// 导出引用内部函数的函数
export function sayHelloByAuthor(name) {
return `${author}: ${sayHello(name)}`
}
main.js
// 析构引入
import { author, sayHello, sayHelloByAuthor } from '../assets/data'
// 整体引入
import * as greetings from '../assets/data'
10.字符串的新增方法
实例方法:includes(), startsWith(), endsWith()
传统上,JavaScript 只有indexOf
方法,可以用来确定一个字符串是否包含在另一个字符串中。ES6 又提供了三种新方法。
includes():返回布尔值,表示是否找到了参数字符串。
startsWith():返回布尔值,表示参数字符串是否在原字符串的头部。
endsWith():返回布尔值,表示参数字符串是否在原字符串的尾部。
实例方法:repeat()
repeat
方法返回一个新字符串,表示将原字符串重复n
次。
实例方法:padStart(),padEnd()
ES2017 引入了字符串补全长度的功能。如果某个字符串不够指定长度,会在头部或尾部补全。padStart()
用于头部补全,padEnd()
用于尾部补全。
实例方法:trimStart(),trimEnd()
const s = ' abc ';
s.trim() // "abc"
s.trimStart() // "abc "
s.trimEnd() // " abc"
11.正则的扩展
数组
使用扩展运算符(...)拷贝数组。
const items1 = [1, 2, 3, 4];
// 这种直接复制,items,items2指向同一地址,改变其中一个,另一个也会跟着改变
const itemsC = items1;
items1[0] = 6;
console.log('直接赋值:');
console.log(items1);
console.log(itemsC);
// bad
const items2 = [1, 2, 3, 4];
const len = items2.length;
const itemsCopy1 = [];
let i;
for (i = 0; i < len; i++) {
itemsCopy1[i] = items2[i];
}
items2[0] = 5;
console.log('循环拷贝的方式:');
console.log(items2);
console.log(itemsCopy1);
// good
const items3 = [1, 2, 3, 4];
const itemsCopy2 = [...items3];
items3[0] = 5;
console.log('...语法方式:');
console.log(items3);
console.log(itemsCopy2);
结果:
直接赋值:
[ 6, 2, 3, 4 ]
[ 6, 2, 3, 4 ]
循环拷贝的方式:
[ 5, 2, 3, 4 ]
[ 1, 2, 3, 4 ]
...语法方式:
[ 5, 2, 3, 4 ]
[ 1, 2, 3, 4 ]
函数
使用默认值语法设置函数参数的默认值。
// bad
function handleThings(opts) {
opts = opts || {};
}
// good
function handleThings(opts = {}) {
// ...
}
模块