ES6知识点
let与const
let、const相对与var的特点:
- 命名的变量没有变量提升。
- 块级作用域的作用,在块以外无法访问变量。
- 不能重复声明。
而const还有个额外的特性不允许被修改。
注意const与对象:用const来声明一个对象,不能直接修改对象,但是可以修改对象中的属性。
模板字符串
模板字符串= 反引号 + ${}表明变量。
在拼接字符串与变量时不需要使用+号来分割,只需要给变量用${}括起来即可。
函数参数默认值
ES6可以在当调用函数没有给定参数的情况下赋予参数默认值。
参数默认值可以是具体参数或者函数。
//具体参数
function add(a = 10, b = 20){
return a + b;
}
add(); //30
add(20); //40
//函数
function add(a = 10, b = getVal(5)){
return a + b;
}
function getVal(c){
return c + 5;
}
add(); //20
... -> 形参剩余/实参拓展
函数剩余参数符
在函数的形参中可以使用 ...xxx 形式来接收实参中多余的参数,得到的是一个存储多余参数的真实数组xxx。
function test(a, ...k){
console.log(k)
}
test(10,20,"hello"); //[20, 'hello']
函数拓展运算符
在函数的实参中使用拓展运算符可以将数组的各个项作为分离的参数传给函数。
const arr = [10,20,30,40];
console.log(Math.max(...arr)); //40
箭头函数
箭头函数写法:
let fn = () => {}
//()填写参数
//{}是函数内容
this指向:
//在ES5函数中,this指向的是调用该函数的上下文。
//在ES6箭头函数中,this指向的是代码中的作用域链。
解构赋值
解构赋值是为了一次性取对象/数组的多个属性。
遵循格式: let {} = {} 或 let [] = [];
对象解构:对相同属性名的属性进行解构
//需要相同属性名
let a = {
b: 10,
c: 20
}
let {c,b,d} = a;
console.log(c,b,d) //20 10 undefined
数组解构:
let a = [10,20,30];
let [b,c,d] = a;
console.log(b,c,d); //10 20 30
对象简写方式
在对象定义时,
- 如果内部属性会用到已经存在的变量可以简写。
- 函数简写可以省去关键字。
let name = 'jack'
let obj = {
name, //相对于ES5的 name: name;
sayHi(){} //相对于ES5的 sayHi: function(){}
}
对象新增方法
Object.is()判断两个东西是否严格相等。
Object.assign()合并对象,属于浅拷贝。
Set数据类型
Set表示不重复的集合。
//定义
let set = new Set();
//添加
set.add(2); //Set(1) {2}
set.add("4"); //Set(2) {2, '4'}
set.add("4"); //Set(2) {2, '4'}
//删除
set.delete(2); //Set(1) {'4'}
//查找
set.has('4'); //true
//长度
set.size //1
Map数据类型
Map是键值对列表。
let map = new Map()
map.set('name','zhangsan')
console.log(map) //Map(1) {'name' => 'zhangsan'}
iterator
迭代器是一种新的遍历机制,是用于遍历数据结构的指针,能够记录遍历的位置。
先有一个数据结构,才能生成它的迭代器。
//生成迭代器
const items = ['one','two']
const ite = items[Symbol.iterator]();
每次使用一次迭代器的next()方法,就会得到一个数据,然后指针向下移动。
// iterator.next()
console.log(ite.next()); //{value: 'one', done: false}
console.log(ite.next()); //{value: 'two', done: false}
console.log(ite.next()); //{value: undefined, done: true}
generator
generator函数,运行后返回值是一个发生器。
发生器使用next()函数才会运行直至下一个断点处。
// 函数命名在function后面标上*
function* gogo(){
console.log('start')
yield 2
console.log('still')
yield 3
console.log('more')
//yield只能在generator函数中使用
}
let fn = gogo()
fn.next() //start {value: 2, done: false}
fn.next() //still {value: 3, done: false}
fn.next() //more {value: undefined, done: true}
promise
promise有三个状态:
-
第一个状态是pending(即处于构造函数执行异步操作时)。
-
第二个状态是resolved,得到成功结果。
-
第三个状态是rejected,得到失败结果。
promise构造函数:
参数:它的参数是一个以两个函数(resolved,rejected)为参数的函数。同时也是在这个函数里面做异步操作的。
返回值:是一个promise对象,此对象中含有then()函数。
promise对象:
- promise对象有方法then():then函数的参数也是两个函数,对应接收resolved,rejected函数接收的值。
- then()的返回值也是一个promise对象。
- promise对象还有方法catch( (error) => {} )等价于then( null, (err) => {} ),即预测到错误并捕获或者只需要错误信息时使用的方法。
初步模拟promise操作:
let pm = new Promise((resolved,rejected) => {
//假设后端返回的数据
let res = {
code: 200, //201
data: {
msg: '成功了'
},
error: {
msg: '失败了'
}
}
//假设异步操作
setTimeout(() => {
if(res.code === 200){
resolved(res.data)
}else{
rejected(res.error)
}
})
})
//得到上面异步操作的返回结果
pm.then((val) => {
console.log(val)
}, (err) => {
console.log(err)
})
// result
// res.code = 200 时,{msg: '成功了'}
// res.code = 201 时,{msg: '失败了'}
升级版模拟promise操作:
//将promise对象作为函数的返回值
function timeOut(ms){
return new Promise((resolved,rejected) => {
setTimeout(() => {
resolved('promise success')
}, ms)
})
}
timeOut(2000).then((val) => {
console.log(val)
})
promise模拟ajax
// 对比
// var xhr = new XMLHttpRequest();
// xhr.open('GET', 'http://suggest.taobao.com/sug?code=utf-8&q=商品关键字&callback=cb');
// xhr.responseType = 'json'
// xhr.setRequestHeader('Accept', 'application/json')
// xhr.send();
// xhr.onreadystatechange = function() {
// if (xhr.readyState == 4 && xhr.status == 200) {
// console.log(xhr.responseText);
// } else {
// console.log(xhr.statusText);
// }
// };
//promise封装
function getJSON(url) {
return new Promise((resolved, rejected) => {
const xhr = new XMLHttpRequest()
xhr.open('GET', url);
xhr.responseType = 'json'
xhr.setRequestHeader('Accept', 'application/json')
xhr.send();
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && xhr.status == 200) {
resolved(xhr.response);
} else {
rejected(xhr.statusText);
}
};
})
}
getJSON('https://free-api.heweather.net/s6/weather/now?location=beijing&key=4693ff5ea653469f8bb0c29638035976')
.then((data) => {
console.log(data)
}, (err) => {
console.log(err)
})
Promise对象的其他方法
all()方法:让多个promise对象并行执行异步操作。
let promise1 = new Promise(() => {})
let promise2 = new Promise(() => {})
let promise3 = new Promise(() => {})
let p4 = Promise.all([promise1, promise2, promise3])
p4.then(() => {
//只有三个都成功才成功
}).catch(err => {
//三个有一个失败就失败
})
race()方法:设置请求的最长时间,超出限制时间就会返回错误。
async
async是基于promise的异步解决方法,并由于promise,易于阅读操作方便。
基本使用:在函数前加上async关键字,async函数会返回一个promise对象
async function f(){}
await:
await命令只能在async函数中使用。
使用后async函数返回的promise对象使用then()只能等待函数中所有await命令执行完之后才调用。
async函数里的后续命令要等待await完成
async函数外的后续命令不用等待await完成
ES6模块化
普通暴露/导入:
- 在定义变量时同时用
export
暴露数据。 - 别的模块导入数据
// one module
export xxx
// other module
import { xxx, xxx, xxx } from module
例子:
// a.js
export let name = 'jack'
export function sayHi(){}
// b.js
import { name, sayHi } from './a.js'
一次性导入一个模块暴露出来的所有数据:
// 语法
import * as xxx from module
// 例子
import * as a from './a.js'
console.log(a.name)
a.sayHi()
默认暴露:(三种方法)
- 每个模块只能用一次,每个模块可以将一个变量、函数或者类作为默认值暴露出去。
// 1. 定义的时候就暴露
export default function(){
console.log('方法1暴露函数为默认值');
}
// 2. 先定义后暴露
let name = 'doug';
export default name;
// 3. 将这个值用 as 命名为 default 暴露
class Student{ // ... }
export {Student as default};
- 导入默认值的语法和导入非默认值的语法略有不同. 导入一个模块暴露出的默认值, 并不用
{}
来包裹, 而且不用使用as
关键字就可以将这个默认值重命名: 例如导入上面例子中的 name, 并将其重命名为 familyName
import familyName from './a.js';
同时导入默认值和非默认值的语法:
import 默认值 { 非默认值 } from './a.js';
ES6转换成ES5
babel:ES6的编译器,可以将ES6的代码转换成ES5的代码,从而让浏览器获得支持。