新特性有四大类:
1、解决原有语法上的一些问题或不足
2、对原有语法进行增强
3、全新的对象,全新的方法,全新的功能
4、全新的数据类型和数据结构
一、Let,Const和块级作用域
在ES2015之前,只有全局作用域和函数作用域,现在可以声明Let和Const它们都属于块级作用域中的定义变量,并且不会声明提前。
for (let i = 0; i < 3; i++) {
let i = 'foo'
console.log(i)
}
二、数组和对象的解构
我们可以这样来解构数组和对象:
const [foo, bar, baz] = arr
const { name } = obj
三、模板字符串
模板字符串(`)支持换行,支持通过表达式${}插入一些参数。
function myTagFunc (strings, name, gender) {
// console.log(strings, name, gender)
const sex = gender ? 'man' : 'woman'
return strings[0] + name + strings[1] + sex + strings[2]
}
const result = myTagFunc`hey, ${name} is a ${gender}.`
我们也可以像这样给他定义一个标签,他会运行这个方法来替换其中的内容
四、字符串的一些扩展方法
const message = 'Error: foo is not defined.'
console.log(
message.startsWith('Error')
message.endsWith('.')
message.includes('foo')
)
五、function参数默认值
我们可以通过function(value = true){}来传入一个默认值,带有默认值的参数应该位置尽量靠后。
六、剩余参数
我们可以通过function(value,...args){}来传入一个剩余参数,这种参数只可以使用一次,并且只能在最后一位。
七、展开数组
const arr = [1,2,3]; consoel.log(...arr); // 1 2 3
八、箭头函数
普通函数 function (){} 箭头函数 () => {}; v => v + 1 ;
只有一条语句时,可以不加{},不加{}时,这一条语句会当做结果return出来。
另外箭头函数没有this声明,他会继续沿用外层的this指向。
九、ES2015中的对象字面量的增强
const bar = '345'
const obj = {
foo: 123,
// bar: bar
// 属性名与变量名相同,可以省略 : bar
bar,
// method1: function () {
// console.log('method111')
// }
// 方法可以省略 : function
method1 () {
console.log('method111')
// 这种方法就是普通的函数,同样影响 this 指向。
console.log(this)
},
// Math.random(): 123 // 不允许
// 通过 [] 让表达式的结果作为属性名
[Math.random()]: 123
}
十、Object扩展方法assgin与is
const obj = { name: 'global obj' };
const funObj = Object.assign({},obj);
console.log(
0 == false // => true
0 === false // => false
+0 === -0 // => true
NaN === NaN // => false
Object.is(+0, -0) // => false
Object.is(NaN, NaN) // => true
)
十一、Proxy对象
const person = {
name: 'zce',
age: 20
}
const personProxy = new Proxy(person, {
get (target, property) {
console.log('get', property)
return target[property]
},
set (target, property, value) {
console.log('set', property, value)
target[property] = value
}
})
personProxy.name = 'jack'
console.log(personProxy.name)
用于监听对象的属性修改和读取行为
十二、静态类Reflect
Reflect一共有十三种方法,整理了一些比较散乱的对象操作,用于替换以前的一些方法,在这里举3个比较常用的例子。
const obj = {
name: 'zce',
age: 18
}
// console.log('name' in obj)
// console.log(delete obj['age'])
// console.log(Object.keys(obj))
console.log(Reflect.has(obj, 'name'))
console.log(Reflect.deleteProperty(obj, 'age'))
console.log(Reflect.ownKeys(obj))
十三、Promise
用于更简洁便利,能够链式调用的异步方法。
十四、Class 定义类
class Person {
//构造函数
constructor (name) {
this.name = name
}
static of (name){
return new Person(name)
}
say () {
console.log(`hi, my name is ${this.name}`)
}
}
十五、Class的继承
class MyPromise extends Promise{
//super代表父类
super.resolve()
}
十六、Set数据结构
常用于面试题数组去重 const result = [...new Set([1,1,1,1,2,3,4])] // [1,2,3,4]
const s = new Set()
s.add(1).add(2).add(3).add(4).add(2)
s.forEach(i => console.log(i))
console.log(s.size)
console.log(s.has(100))
console.log(s.delete(3))
s.clear()
十七、Map数据结构
Map才是真正意义上的键值对集合,他可以用任意类型的值作为key,而对象只能用字符串作为key。
const m = new Map()
const tom = { name: 'tom' }
m.set(tom, 90)
console.log(m)
console.log(m.get(tom))
// m.has()
// m.delete()
// m.clear()
m.forEach((value, key) => {
console.log(value, key)
})
十七、生成器函数 Generator
使用function * foo(){},yield作为断点代替return,再用foo.next()来继续执行。
以下是配合Promise的一个异步方案:
function ajax (url) {
return new Promise((resolve, reject) => {
var xhr = new XMLHttpRequest()
xhr.open('GET', url)
xhr.responseType = 'json'
xhr.onload = () => {
if (xhr.status === 200) {
resolve(xhr.response)
} else {
reject(new Error(xhr.statusText))
}
}
xhr.send()
})
}
function * main () {
try {
const users = yield ajax('/api/users.json')
console.log(users)
const posts = yield ajax('/api/posts.json')
console.log(posts)
const urls = yield ajax('/api/urls.json')
console.log(urls)
} catch (e) {
console.log(e)
}
}
function co (generator) {
const g = generator()
function handleResult (result) {
if (result.done) return // 生成器函数结束
result.value.then(data => {
handleResult(g.next(data))
}, error => {
g.throw(error)
})
}
handleResult(g.next())
}
co(main)
十八、Symbol数据类型
继String、Number、Null、Undefined、Boolean、Object之后的第七种数据类型
可防止扩展对象,属性名冲突问题,两个 Symbol 永远不会相等,可以使用 Symbol 为对象添加用不重复的键,实现对象的实现私有成员。
const name = Symbol()
const person = {
[name]: 'zce',
say () {
console.log(this[name])
}
}
十九、iterator迭代器
在一个对象中声明迭代器,可以对外抛出一个遍历的接口。这也就是for...of的原理,我们可以将这个迭代器在任意对象中进行声明,然后赋予一个我们想要的方法,对外暴露一个循环的方法。内部挂载一个生成器函数Generator,外部其实是使用循环+next()的方式实现的。
const todos = {
life: ['吃饭', '睡觉', '打豆豆'],
learn: ['语文', '数学', '外语'],
work: ['喝茶'],
[Symbol.iterator]: function * () {
const all = [...this.life, ...this.learn, ...this.work]
for (const item of all) {
yield item
}
}
}
for (const item of todos) {
console.log(item)
}