ECMAScript 和 Javascript 的关系
- ES是JS的标准化规范
- JS是ES的扩展语言(在ES的基础之上)
- 浏览器环境中的JS = ES + Web APIs
- Node环境中的JS = ES + Node APIs
- JS本身指的就是ES
ECMAScript2015的新特性
ES6 特指ES2015,泛指ES5.1之后的所有版本
1.声明变量
- let,块级作用域
- const,常量
- var,原有的变量声明方式
最佳实践:不用var,主用const,配合使用let
2.数组的解构
// 获取数组的每个元素
const arr = [11, 22, 33]
// 不使用解构
const a1 = arr[0]
const a2 = arr[1]
const a3 = arr[2]
// 使用解构
const [a1, a2, a3] = arr
console.log(a2) //22
const [a1, a2, a3, a4] = arr
console.log(a4) //undefined
// 剩余参数
const [a1, ...rest] = arr
console.log(rest) //22, 33
// 默认值
const [a1, a2, a3, a4='default value'] = arr
console.log(a4) //default value
3.对象的扩展
3.1 对象的解构
const obj = {name: 'flower', age: 18}
const {name, age} = obj
console.log(name, age)
// 重命名
const {name: myName} = obj
console.log(myName)
// 默认值
const {name: myName='box', age, sex='女'} = obj
console.log(myName, age, sex) //flower 18 女
3.2 对象字面量增强
- 属性简写
const name = 'Tom'
const obj = {
name, //属性名就是变量名,属性值是变量值
age: 18
}
- 方法简写
const obj = {
fn: function(){
//原来的写法
},
fnn(){
//新的写法
}
}
- 计算属性
可以用表达式的值作为属性名,需要放在中括号里
const prop1 = 'x'
const prop2 = 'y'
const obj = {
[prop1]: 1,
[prop2]: 2
}
obj //{x: 1, y: 2}
3.3 对象新增方法
- Object.assign(targetObj, …sourceObj)
将多个源对象中的属性复制到目标对象,并返回目标对象 - Object.is(a, b)
判断两个值是否相等
0==false //true
0===false //false
+0 === -0 //true
NaN === NaN //false
Object.is(+0, -0) //false
Object.is(NaN, NaN) //true
3.4 Proxy 对象代理
为对象设置访问代理器,监听对象的读写过程
const person = {
name: 'Tom',
age: 18
}
const personProxy = new Proxy(person, {
get: function(target, property){
//读取某个属性
return property in target ? target[property] : 'default value'
// get方法的返回值就是读取到的属性值
// return 100
},
set: function(target, property, value){
//写入某个属性
target[property] = value
console.log(target, property, value)
},
has: function(){
//in 判断是否存在某个属性
},
deleteProperty: function(){
//delete 删除属性
},
apply: function(){
//调用一个函数
},
... //共13种代理函数
})
console.log(personProxy.name)
personProxy.age = 20
与Object.defineProperty的区别:
- 对Proxy实例进行操作,而不是目标对象
- Proxy还可以监听数组
- Object.defineProperty(target, property, {})需要对目标对象的每个属性指定get和set方法
- Object.defineProperty只能监听对目标对象的读写
3.5 Reflect
提供了一套统一的用于操作对象的API,共有13个静态方法,与Proxy对象的方法一一对应
const obj = {
console.log('name' in obj)
console.log(delete obj['age]')
console.log(Object.keys(obj))
//使用Reflect
console.log(Reflect.has(obj, 'name'))
console.log(Reflect.deleteProperty(obj, 'age'))
console.log(Reflect.ownKeys(obj))
}
4.字符串扩展
4.1 模版字符串
- 用反引号 `` 标识
- 可以换行
- 可以嵌入变量: ${变量名}
- 可以嵌入并计算js表达式: ${表达式}
标签模版
- 标签模版是函数调用的一种特殊形式,标签是函数,模版字符串是它的参数。
//console.log就是一个函数
console.log`aaa` //['aaa']
- 如果模版字符串中有变量,会将模版字符串处理成多个参数,再调用:
- 第一个参数是数组,数组成员是模版字符串中没有变量替换的部分(静态内容)
- 其他参数是模版字符串中变量的值
let a = 5;
let b = 10;
function tag(strings, value1, value2){
console.log(strings) //[ 'Hello ', ' world ', '' ]
console.log(value1) //5
console.log(value2) //10
// return 123
return strings[0]+strings[1]
}
const result = tag`Hello ${a} world ${b}`;
console.log(result)
4.2 字符串新增方法
- includes()
判断字符串中是否包含参数字符串 - startsWith()
判断字符串是否以参数字符串开始 - endsWith()
判断字符串是否以参数字符串结尾
5.函数的扩展
5.1 参数的默认值和剩余参数
带有默认值的参数只能放在后边
function fn(x, y=2){
console.log(x+y)
}
fn(3, 1) //4
fn(3) //5
剩余参数只能定义在形参的最后
function fpp(){
console.log(arguments)
}
function foo(...args){
console.log(args)
}
fpp(1, 2, 3) //[Arguments] { '0': 1, '1': 2, '2': 3 }
foo(1, 2, 3) //[ 1, 2, 3 ]
用…展开数组,主要用于函数调用,相当于rest参数的逆运算,将一个数组转换为逗号隔开的参数序列
function add(x, y, z){
console.log(x+y+z)
}
const numbers = [1,2,3]
add(...numbers) //
5.2 箭头函数
(参数) => { 返回值 }
6.Class
- 实例方法
通过类创造的实例对象调用的方法 - 静态方法 static
通过类本身调用的方法 - 私有成员
只有类本身可以访问的成员 - 继承 extends
class Person {
constructor(name){
this.name = name
}
say(){
consloe.log(`my name is ${this.name}`)
}
}
class Student extends Person{
constructor(name, number){
super(name) //通过super调用父类的构造函数
this.number = number
}
hello(){
super.say() //通过super访问父类的成员
console.log(`my number is ${this.number}`)
}
}
const s = new Student('Tom', 61)
s.hello()
7.Set 集合
类似数组,但集合中的成员不可重复
const s = new Set()
//1.通过add方法向set对象添加成员
//2.add方法返回一个set对象,所以可以链式调用
s.add(1).add(3).add(5)
console.log(s) //Set { 1, 3, 5 }
//Set可以接受一个数组为参数
const y = new Set([2,4,6,8])
console.log(y) //Set { 2, 4, 6, 8 }
console.log([...y]) //[ 2, 4, 6, 8 ]
8.Map 映射
类似对象的键值对集合,键可以是任意数据类型
const m = new Map()
// 通过set方法添加成员
const obj = {name: 'Jarry'}
m.set(obj, 18)
console.log(m)
// 通过set方法获取成员
console.log(m.get(obj))
// Map接受一个键值对数组作为参数
==TODO==
9.Symbol
JS的第七种原始数据类型,主要作用是为对象添加独一无二都属性名,避免冲突
JS的七种原始数据类型:
- undefined
- null
- 布尔值
- 字符串类型
- 数值类型
- 对象类型
let s = Symbol();
typeof s // symbol
const s1 = Symbol()
const s2 = Symbol()
console.log(s1 === s2) //false
const obj = {
s: 123,
[s]: 456
}
console.log(obj.s) //123
console.log(obj[s]) //456
console.log(obj['s']) //123
- symbol值作为对象的属性名时,不能用.运算符,只能放在中括号中
- 使用for…in遍历对象,或者Object.keys(obj),是不能获取到symbol属性的
- 要想获取对象都symbol属性,可以通过Object.getOwnPropertySymbols(obj)
Symbol.for()方法
const s3 = Symbol.for()
const s4 = Symbol.for()
console.log(s3 === s4) //true
10.for…of循环
以后将作为遍历所有数据结构都统一方式,但不能直接用来遍历普通的对象,因为对象没有实现iterable接口。
for(const item of arr){
console.log(item)
//可以使用break跳出循环
if(item > 100){
break
}
}
常见都遍历方式:
- for循环
- for…in 遍历键值对
for(let key in obj){
consloe.log(obj[key])
}
- forEach方法 遍历数组
obj.forEach(item => {
console.log(item)
})
。。。
11.Iterator 遍历器
11.1 iterable 可迭代接口
能够用for…of循环都数据结构都实现了iterable接口,也就是说结构本身具有Symbol.iterator属性,这个属性本身是一个遍历器生成函数,执行这个函数,会返回一个遍历器对象,执行该对象的next方法,会返回一个代表当前成员的信息对象,包含value和done两个属性。
11.2 实现可迭代接口
为对象类型实现可迭代接口
const obj = {
store: ['foo', 'bar', 'baz'],
[Symbol.iterator]: function(){
let index = 0
const self = this
return {
next: function(){
const result = {
value: self.store[index],
done: index >= self.store.length
}
index++
return result
}
}
}
}
for(const item of obj){
console.log(item)
}
ECMAScript2016
- 新增数组方法 includes
//可以判断是否有NaN,但indexOf不可以
const arr = [1, 2, 3, NaN]
arr.indexOf(NaN) //-1
arr.includes(NaN) //true
- 新增指数运算符
//计算2的10次方
console.log(2 ** 10) //1024
ECMAScript2017
- Object.values(obj)
获取对象所有的值(keys方法是获取所有的键) - Object.entries(obj)
以数组形式返回对象的键值对 - Object.getOwnPropertyDescriptors(obj)
获取对象属性的完整描述信息。通过Object.assign复制的对象会将getter和setter属性当作普通属性而不是方法来复制
const p1 = {
firstName: 'He',
lastName: 'Pan',
get fullName = this.firstName + ' ' + this.lastName
}
console.log(p1.fullName)
const p2 = Object.assign({}, p1)
p2.firstName = 'Hua'
console.log(p2.fullName) //He Pan
const descriptors = Object.getOwnPropertyDescriptors(p1)
console.log(descriptors)
const p3 = Object.defineProperties({}, descriptors)
p3.firstName = 'Hua'
console.log(p3.fullName) //Hua Pan
- padStart和padEnd
用指定字符补全字符串到指定长度
str.padStart(length, 指定字符)