ES6
1.let变量声明以及声明特性
1.1 变量不能重复声明
let star = '罗志祥'
let star = '小猪' //报错
复制代码
1.2 块级作用域 全局,函数,eval
//if else while for
{
let girl = '范爷'
}
console.log(girl) //报错
复制代码
1.3不存在变量提升
console.log(song) //报错
let song = '恋爱达人'
复制代码
1.4不影响作用域链
{
let school = '北大'
function fn(){
console.log(school)
}
fn()
}
复制代码
let经典案例:遍历绑定事件
for(let i=0;i<items.length;i++){
items[i].onclick = function(){
//this.style.background = 'pink'
items[i].style.background = 'pink'
}
}
复制代码
2.常量的声明以及声明特性
2.1声明常量
const school = '北大'
复制代码
2.2一定要赋初始值
const A //报错
复制代码
2.3一般常量使用大写(潜规则)
const a = 100
复制代码
2.4常量的值不能修改
school = 'beida' //报错
复制代码
2.5块级作用域
{
const PLAYER = 'UZI'
}
console.log(PLAYER) //报错
复制代码
2.6对于数组和对象的元素修改,不算做常量的修改,不会报错
const TEAM = ['UZI','MXLG','Ming','Letme']
TEAM.push('Meiko')
复制代码
3.变量的解构赋值
解构赋值:ES6允许按照一定模式从数组和对象中提取值,对变量进行赋值
3.1数组的解构
const F4 = ['小沈阳','刘能','赵四','宋小宝']
let [xiao, liu, zhao, song] = F4
console.log(xiao)
console.log(liu)
console.log(zhao)
console.log(song)
复制代码
3.2对象的解构
const zhao = {
name: '赵本山',
age: '不详',
xiaopin: function(){
console.log('我可以演小品')
}
}
//对象用花括号进行解构
let {name, age, xiaopin} = zhao
console.log(name)
console.log(age)
console.log(xiaopin)
xiaopin()
复制代码
3.3如果解构不成功,变量的值就等于undefined
let [foo] = []
let [bar, foo] = [1]
//以上两种情况都属于解构不成功,foo的值都会等于undefined
复制代码
4.模板字符串
ES6引入新的声明字符串的方式 “, ‘ ‘, “”
4.1声明
let str = `我也是一个字符串哦!`
console.log(str,typeof str)
复制代码
4.2内容中可以直接出现换行符
let str = `<ul>
<li>沈腾</li>
<li>玛丽</li>
<li>艾伦</li>
</ul>`
复制代码
4.3变量拼接(常用)
let lovest = '魏翔'
let out = `${lovest}是最搞笑的演员!!`
console.log(out)
复制代码
5.简化对象写法
ES6 允许在大括号里面直接写入变量和函数,作为对象的属性和方法
let name = '北大'
let change = function(){
console.log('最高学府!')
}
const school = {
name,
change,
//方法的简化写法
impove(){
console.log('提高你的技能')
}
}
复制代码
6.箭头函数
ES6 允许使用 [箭头] (=>)定义函数
//声明一个函数
//let fn =function(){
//
//}
let fn = (a,b) => {
return a+b
}
//调用函数
let result= fn(1,2)
console.log(result) //3
复制代码
6.1this是静态的,this始终指向函数声明时所在作用域下的this的值
function getName(){
console.log(this.name)
}
let getName2 = () => {
console.log(this.name)
}
//设置 window 对象的 name 属性值
window.name = '北大'
const school = {
name: '清华'
}
//直接调用
getName() //北大
getName2() //北大
//call 方法调用
getName.call(school) //清华
getName2.call(school) //北大
复制代码
6.2不能作为构造函数实例化对象
let Person = (name, age) => {
this.name = name
this.age = age
}
let me = new Person('xiao',17)
console.log(me) //报错
复制代码
6.3不能使用 arguments 变量
let fn = () =>{
console.log(arguments)
}
fn(1,2,3) //报错
复制代码
6.4箭头函数的简写
//1)省略小括号, 当形参有且只有一个的时候
let add = n => {
return n + n
}
console.log(add(9)) //18
//2)省略花括号, 当代码体只有一条语句的时候, 此时 return 必须省略
// 而且语句的执行结果就是函数的返回值
let pow = n => n * n
console.log(pow(8)) //64
复制代码
6.5箭头函数实践
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>箭头函数实践</title>
<style>
div {
width: 200px;
height: 200px;
background: #58a;
}
</style>
</head>
<body>
<div id="ad"></div>
<script>
//需求-1 点击 div 2s 后颜色变成粉色
let ad = document.getElementById('ad')
ad.addEventListener('click',function(){
//保存 this 的值
// let _this = this
//定时器
setTimeout(() => {
//修改背景颜色 this
// console.log(this)
// _this.style.background = 'pink'
this.style.background = 'pink' //this指向ad
}, 2000)
})
//需求-2 从数组中返回偶数的元素
const arr = [1,6,9,10,100,25]
// const result = arr.filter(function(item){
// if(item%2 === 0){
// return true
// }else{
// return false
// }
// })
const result = arr.filter(item => item%2 === 0)
console.log(result)
//箭头函数适合与 this 无关的回调. 定时器, 数组的方法回调
//箭头函数不适合与 this 有关的回调. 事件回调, 对象的方法
</script>
</body>
</html>
复制代码
7.函数参数默认值
ES6允许给函数参数赋值初始值
7.1形参初始值 具有默认值的参数, 一般位置要靠后(潜规则)
function add(a,b,c=10){
return a+b+c
}
let result = add(1,2)
console.log(result) //13
复制代码
7.2与解构赋值结合
function connect({host='127.0.0.1', username, password, port}){
console.log(host)
console.log(username)
console.log(password)
console.log(port)
}
connect({
host: 'localhost',
username: 'root',
password: 'root',
port: '3306'
})
复制代码
8.rest参数
ES6 引入 rest 参数,用于获取函数的实参,用来代替 arguments
ES5 获取实参的方式
function date(){
console.log(arguments)
}
date('柏芝','阿娇','思慧')
复制代码
rest 参数,必须放到最后,否则会报错
function date(...args){
console.log(args) //数组形式 可使用filter some every map 等方法
}
date('柏芝','阿娇','思慧')
复制代码
9.扩展运算符
[…] 扩展运算符能将 [数组] 转换为逗号分隔的 [参数序列]
const tfboys = ['易烊千玺','王源','王俊凯']
function chunwan(){
console.log(arguments)
}
chunwan(...tfboys) //chuanwan('易烊千玺','王源','王俊凯')
复制代码
扩展运算符应用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>扩展运算符应用</title>
</head>
<body>
<div></div>
<div></div>
<div></div>
<script>
//1.数组的合并
const kuaizi = ['王太利','肖央']
const fenghuang = ['曾毅','玲花']
// const zuixuanxiaopingguo = kuaizi.concat(fenghuang)
const zuixuanxiaopingguo = [...kuaizi,...fenghuang]
console.log(zuixuanxiaopingguo)
//2. 数组的克隆 浅拷贝
const sanzhihua = ['E','G','M']
const sanyecao = [...sanzhihua]
console.log(sanyecao)
//3. 将伪数组转为真正的数组
const divs = document.querySelectorAll('div')
const divArr = [...divs]
console.log(divArr)
</script>
</body>
</html>
复制代码
10.Symbol
10.1 ES6引入了一种新的原始数据类型Symbol, 表示独一无二的值。
它是JavaScript语言的第七种数据类型,是一种类似于字符串的数据类型。
Symbol特点
1)Symbol的值是唯一的,用来解决命名冲突的问题
2)Symbol值不能与其他数据进行运算
3) Symbol 定义的对象属性不能使用for..in 循环遍历,但是可以使用
Reflect.ownKeys来获取对象的所有键名
//创建Symbol
let s = Symbol()
//console.log(s,typeof s)
let s2 = Symbol('北大')
let s3 = Symbol('北大')
console.log(s2 === s3) //false
//Symbol.for 创建
let s4 = Symbol.for('北大')
let s5 = Symbol.for('北大')
console.log(s4 === s5) //true
//不能与其他数据进行运算
//let result = s + 100
//let result = s > 100
//let result = s + s
//js 7种原始数据类型
//u undefined
//s string symbol
//o object
//n number null
//b boolean
复制代码
10.2 Symbol 创建对象属性
//向对象中添加方法 up down
let gane = {
name: '俄罗斯方块',
up: function(){},
down: function(){}
}
//声明一个对象
//let methods = {
// up: Symbol(),
// down: Symbol()
//}
//game[method.up] = function(){
// console.log('改变形状')
//}
//game[method.down] = function(){
// console.log('快速下降')
//}
let youxi = {
name: '狼人杀',
[Symbol('say')]: function(){
console.log('发言')
},
[Symbol('zibao')]: function(){
console.log('自爆')
}
}
console.log(youxi)
复制代码
10.3 Symbol内置属性
class Person{
static [Symbol.hasInstance](param){
console.log(param)
console.log('我被用来检测类型了')
return false
}
}
let o = {}
console.log(o instanceof Person) //
const arr = [1,2,3]
const arr2 = [4,5,6]
arr2[Symbol.isConcatSpreadable] = false //不展开
console.log(arr.concat(arr2)) //[1,2,3,Array(3)]
复制代码
11迭代器 Iterator
11.1迭代器(Iterator)是一种接口,为各种不同的数据结构提供统一的访问机制。
任何数据结构只要部署Iterator 接口,就可以完成遍历操作。
- ES6 创造了一-种新的遍历命令for…of循环,Iterator 接口主要供for…of消费
2)原生具备iterator接口的数据(可用for of遍历)
a) Array
b) Arguments
c) Set
d) Map
e) String
f ) TypedArray
g) NodeList
3)工作原理
a)创建一个指针对象, 指向当前数据结构的起始位置
b)第一次调用对象的next方法,指针自动指向数据结构的第一个成员
c) 接下来不断调用next方法,指针一直往后移动,直到指向最后一个成员
d)每调用next方法返回一个包含value和done属性的对象
注:需要自定义遍历数据的时候,要想到迭代器。
//声明一个数组
const xiyou = ['唐僧','孙悟空','猪八戒','沙僧']
//使用 for...of 遍历数组 键值/for...in 遍历 键名
for(let v of xiyou){
console.log(v)
}
let iterator = xiyou[Symbol.iterator]()
//调用对象的next方法
console.log(iterator.next())
console.log(iterator.next())
console.log(iterator.next())
console.log(iterator.next())
console.log(iterator.next())
复制代码
11.2 自定义遍历数据
//声明一个对象
const banji = {
name: '终极一班',
stus: [
'xiaoming',
'xiaotian',
'xiaodong',
'xiaonan'
],
[Symbol.iterator](){
//索引变量
let index = 0
//保存this
let _this = this
return {
next: function(){
if(index < _this.stus.length){
const result = { value: _this.stus[index],done: false}
//下标自增
index++
return result
}else{
return {value: undefined,done: true}
}
}
}
}
}
//遍历这个对象
for(let v for banji){
console.log(v)
}
复制代码
12.生成器
12.1生成器函数是ES6提供的易中异步编程解决方案,语法行为和传统函数完全不同
//生成器函数其实就是一个特殊的函数
//异步编程 纯回调函数
//yield 函数代码的分隔符
function * gen(){
//console.log('111')
yield '一只没有耳朵'
//console.log('222')
yield '一只没有尾巴'
//console.log('333')
yield '真奇怪'
//console.log('444')
}
let iterator = gen()
console.log(iterator.next())
console.log(iterator.next())
console.log(iterator.next())
console.log(iterator.next())
//遍历
//for(let v of gen()){
// console.log(v)
//}
复制代码
12.2生成器函数参数传递
function * gen(arg){
console.log(arg)
let one = yield 111
console.log(one) //BBB
let two = yield 222
console.log(two) //CCC
let three = yield 333
console.log(three) //DDD
}
let iterator = gen('AAA')
console.log(iterator.next())
//next方法可以传入实参
console.log(iterator.next('BBB')) //传入的参数作为第一个yeild 的返回结果
console.log(iterator.next('CCC')) //传入的参数作为第二个yeild 的返回结果
console.log(iterator.next('DDD')) //传入的参数作为第三个yeild 的返回结果
复制代码
12.3生成器函数实例
//异步编程 文件操作 网络操作(ajax,request) 数据库操作
//1s 后控制台输出111 2s后输出222 3s后输出333
//回调地狱
setTimeout(()=>{
console.log(111)
setTimeout(()=>{
console.log(222)
setTimeout(()=>{
console.log(333)
},3000)
},2000)
},1000)
function one(){
setTimeout(()=>{
console.log(111)
iterator.next()
},1000)
}
function two(){
setTimeout(()=>{
console.log(222)
iterator.next()
},2000)
}
function three(){
setTimeout(()=>{
console.log(333)
iterator.next()
},3000)
}
function * gen(){
yield one()
yield two()
yield three()
}
let iterator = gen()
iterator.next()
复制代码
//模拟获取 用户数据 订单数据 商品数据
function getUsers() {
setTimeout(()=>{
let data = '用户数据'
//调用next方法,并且将数据传入
iterator.next(data)
},1000)
}
function getOrders() {
setTimeout(()=>{
let data = '订单数据'
//调用next方法,并且将数据传入
iterator.next(data)
},1000)
}
function getGoods() {
setTimeout(()=>{
let data = '商品数据'
//调用next方法,并且将数据传入
iterator.next(data)
},1000)
}
function * gen(){
let users = yield getUsers()
let orders = yield getOrders()
let goods = yield getGoods()
}
let iterator = gen()
iterator.next()
复制代码
13.Promise
13.1 Promise是ES6引入的异步编程的新解决方案。语法上Promise是一个构造函数,用来封装异步操作并可以获取其成功或失败的结果。
- Promise 构造函数: Promise (excutor) {}
- Promise.prototype.then 方法 链式调用
- Promise.prototype.catch 方法
//实例化 Promise 对象
const p = new Promise(function(resolve,reject){
setTimeout(()=>{
let data = '数据库中的用户数据'
//指定成功的回调
resolve(data)
let err = '数据读取失败'
//指定失败的回调
reject(err)
},1000)
})
//调用promise对象的then方法
p.then(function(value){//执行成功的回调
console.log(value)
},function(reason){//执行失败的回调
console.error(reason)
})
复制代码
13.2 Promise对象的catch方法
const p = new Promise((resolve,reject)=>{
setTimeout(()=>{
//设置p对象的状态为失败,并设置失败的值
reject('出错了!')
},1000)
})
//p.then(function(value){},function(reason){
// console.error(reason)
//})
p.catch(function(reason){
console.warn(reason)
})
复制代码
13.3 Promise读取文件 需要node环境
//1.引入fs模块
const fs = require('fs')
//2.调用方法读取文件
//fs.readFile('./resources/为学.md',(err,data)=>{
//如果失败,则抛出错误
//if(err) throw err
//如果没有错误,则输出内容
//console.log(data.toString())
//})
//3.使用Promise封装
const p = new Promise((resolve,reject)=>{
fs.readFile('./resources/为学.md',(err,data)=>{
//如果失败
if(err) reject(err)
//如果成功
resolve(data)
})
})
p.then(funstion(value){
console.log(value.toString())
},function(reason){
console.log('读取失败!')
})
复制代码
13.4 Promise-then方法
//创建promise对象
const p = new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve('用户数据')
//reject('出错了!')
},1000)
})
//掉用then方法 then方法的返回结果是 Promise 对象,对象的状态由回调函数的执行结果决定
//如果回调函数中返回的结果是 非 promise 类型的属性,状态为成功,返回值为对象的成功的值
const result = p.then(value=>{
console.log(value)
//1. 非 promise 类型的属性
//return '123'
//2. 是 promise 对象
return new Promise((resolve,reject)=>{
//resolve('ok')
reject('error')
})
//3.抛出错误
//throw new Error('出错了!')
//throw '出错了!'
},reason=>{
console.warn(reason)
})
console.log(reasult)
复制代码
13.5 Promise实践-读取多个文件
//引入fs模块
const fs = require('fs')
fs.readFile('./resources/为学.md',(err,data1)=>{
fs.readFile('./resources/插秧诗.md',(err,data2)=>{
fs.readFile('./resources/观书有感.md',(err,data3)=>{
let result = data1 + '\r\n' + data2 + '\r\n' + data3
console.log(result)
})
})
})
//使用 promise 实现
const p = new Promise((resolve,reject)=>{
fs.readFile('./resources/为学.md',(err,data)=>{
resolve(data)
})
})
p.then(value=>{
return new Promise((resolve,reject)=>{
fs.readFile('./resources/插秧诗.md',(err,data)=>{
resolve([value,data]) //向下传递
})
})
}).then(value=>{
return new Promise((resolve,reject)=>{
fs.readFile('./resources/观书有感.md',(err,data)=>{
//压入
value.push(data)
resolve(value)
})
})
}).then(value=>{
console.log(value.join('\r\n'))
})
复制代码
14.Set集合
14.1 ES6提供了新的数据结构Set (集合)。它类似于数组,但成员的值都是唯一的,集合实现了iterator接口,所以可以使用「扩展运算符」和 for…of进行遍历,
集合的属性和方法:
- size 返回集合的元素个数
- add 增加一个新元素,返回当前集合
- delete 删除元素,返回boolean值
- has 检测集合中是否包含某个元素,返回boolean值
//声明一个 set
let s = new Set()
let s2 = new Set(['大事儿','小事儿','好事儿','坏事儿','小事儿'])
//元素个数
console.log(s2.size)
//添加新元素
s2.add('喜事儿')
//删除元素
s2.delete('坏事儿')
//检测
console.log(s2.has('糟心事'))
//清空
s2.clear()
for(let v of s2){
console.log(v)
}
复制代码
14.2 Set 实践
let arr = [1,2,3,4,5,4,3,2,1]
//1.数组去重
let result = [...new Set(arr)]
//2.交集
let arr2 = [4,5,6,5,6]
let result = [...new Set(arr)].filter(item => new Set(arr2).has(item))
//3.并集
let union = [...new Set([...arr,...arr2])]
console.log(union)
//4.差集
let diff = [...new Set(arr)].filter(item => !(new Set(arr2).has(item)))
复制代码
15.Map
ES6提供了Map数据结构。它类似于对象,也是键值对的集合。但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。Map也实现了iterator 接口,所以可以使用「扩展运算符」和 for… of 进行遍历。Map的属性和方法:
- size 返回Map的元素个数|
- set 增加一个新元素,返回当前Map
- get 返回键名对象的键值
- has 检测Map中是否包含某个元素,返回boolean值
- clear 清空集合,返回undefined
//声明 Map
let m = new Map()
//添加元素
m.set('name','北大')
m.set('change',function(){
console.log('改变人生')
})
let key = {
school: 'beida'
}
m.set(key,['北京','上海','深圳'])
//size
console.log(m.size)
//删除
m.delete('name')
//获取
console.log(m.get('change'))
//清空
m.clear()
//遍历
for(let v of m){
console.log(v)
}
复制代码
16.class类
16.1 ES6提供了更接近传统语言的写法,引入了Class (类)这个概念,作为对象的模板。通过class关键字,可以定义类。基本上,ES6 的class可以看作只是一个语法糖,它的绝大部分功能,ES5 都可以做到,新的class 写法只是让对象原型的写法更加清晰、更像面向对象编程的语法而已。
知识点:
- class 声明类
- constructor 定义构造函数初始化
- extends 继承父类
- super 调用父级构造方法
- static定义静态方法和属性
- 父类方法可以重写
//ES5 通过构造函数创建对象
function Phone(brand,price){
this.brand = brand
this.price = price
}
//添加方法
Phone.prototype.call = function(){
console.log('我可以打电话')
}
//实例化对象
let Huawei = new Phone('华为',5999)
Huawei.call()
//ES6 class
class Shouji{
//构造方法
constructor(brand,price){
this.brand = brand
this.price = price
}
//方法必须使用该语法,不能使用ES5的对象完整式
call(){
console.log('我可以打电话')
}
}
let onePlus = new Shouji('1+',1999)
consloe.log(onePlus)
复制代码
16.2 类的静态成员
//function Phone(){
//
//}
//Phone.name = '手机'
//Phone.change = function(){
// console.log('改变世界')
//}
//Phone.prototype.size = '5.5inch'
//let nokia = new Phone()
//console.log(nokia.name) //undefined
//console.log(nokia.size) //5.5inch
class Phone{
//静态属性
static name = '手机'
static change(){
console.log('改变世界')
}
}
let nokia = new Phone()
console.log(nokia.name) //undefined
console.log(Phone.name) //手机
复制代码
16.3对象继承
//ES5对象继承
//手机
function Phone(brand,price){
this,brand = brand
this.price = price
}
Phone.prototype.call = function(){
console.log('打电话')
}
//智能手机
function SmartPhone(brand,price,color,size){
Phone.call(this,brand,price) //调用call方法,继承Phone的属性
this.color = color
this.size = size
}
//设置子级构造函数的原型
SmartPhone.prototype = new Phone
//声明子类的方法
SmartPhone.prototype.photo = function(){
conosle.log('拍照')
}
const chuizi = new SmartPhone('锤子',2499,'黑色','5.5inch')
console.log(chuizi)
复制代码
class Phone(){
//构造方法
constructor(brand,price){
this,brand = brand
this.price = price
}
//父类的成员属性
call(){
console.log('打电话')
}
}
//类的继承和方法重写
class SmartPhone extends Phone {
//构造方法
constructor(brand,price,color,size){
super(brand,price) //Phone.call(this,brand,price)
this.color = color
this.size = size
}
photo(){
console.log('拍照')
}
//重写父类的方法
call(){
console.log('视频通话')
}
}
const xiaomi = new SmartPhone('小米',799,'黑色','4.7inch')
console.log(xiaomi)
xiaomi.call() //视频通话
xiaomi.photo() //拍照
复制代码
16.4 get 和 set
class Phone{
get price(){
console.log('价格属性被读取了')
return 'iloveyou'
}
set price(newVal){
console.log('价格属性被修改了')
}
}
//实例化对象
let s = new Phone()
//console.log(s.price) //触发get方法
s.price = 'free' //触发set方法
复制代码
17.数值扩展
//0. Number.EPSILON 是 JavaScript 表示的最小精度
//EPSILON 属性的值接近于 2.220446049250313e-16
function equal(a,b){
if(Math.abs(a-b) < Number.EPSILON){
return true
}else{
return false
}
}
console.log(equal(01+0.2,0.3)) //true
//1.二进制和八进制 十进制和十六进制
let b = 0b1010
let o = 0o777
let d = 100
let x = oxff
//2.Number.isFinite 检测一个数是否为有限数
console.log(Number.isFinite(100)) //true
console.log(Number.isFinite(100/0)) //false
console.log(Number.isFinite(Infinity)) //fasle
//3.Number.isNaN 检测一个数值是否为NaN
console.log(Number.isNaN(123))
//4.Number.parseInt Number.parseFloat 字符串转整数、浮点数
console.log(Number.parseInt('5201314love')) //5201314
console.log(Number.parseFloat('3.1415926神奇')) //3.1415926
//5.Number.isInteger 判断一个数是否为整数
consoloe.log(Number.isInteger(5)) //true
consoloe.log(Number.isInteger(2.5)) //false
//6.Math.trunc 将数字的小数部分抹掉
consoloe.log(Math.trunc(3.5)) //3
//7.Math.sign 判断一个数到底是正数 负数 还是零
console.log(Math.sign(100)) // 1
console.log(Math.sign(0)) // 0
console.log(Math.sign(-1000))// -1
复制代码
18.对象方法扩展
//1.Object.is 判断两个值是否完全相等
console.log(Object.is(120,120)) //true
console.log(Object.is(NaN,NaN)) //true
console.log(NaN === NaN) //false
//2.Object.assign 对象的合并
const config1 = {
host: 'localhost',
port: 3306,
name: 'root',
pass: 'root',
text: 'test'
}
const config2 = {
host: 'http://baidu.com',
port: 33060,
name: 'baidu.com',
pass: 'iloveyou',
text2: 'test2'
}
console.log(Object.assign(config1,config2)) //config2覆盖config1相同的属性,不同的属性会保留下来
//3.Object.setPrototypeOf 设置原型对象 Object.getPrototypeOf 获取原型对象
const school = {
name: '北大'
}
const cities = {
xiaoqu: ['北京','上海','深圳']
}
Object.setPrototypeOf(school,cities) //不建议这么做
console.log(Object.getPrototypeOf(school))
console.log(school)
复制代码
19.模块化
19.1 模块化是指将一个大的程序文件,拆分成许多小的文件,然后将小文件组合起来。
19.2 模块化的好处
模块化的优势有以下几点:
- 防止命名冲突
- 代码复用
- 高维护性
19.3 ES6模块化语法
模块功能主要由两个命令构成: export 和import。
●export命令用于规定模块的对外接口
●import命令用于输入其他模块提供的功能
//m1.js
//分别暴露
export let school = '北大'
export function teach(){
console.log('教你技能')
}
复制代码
//m2.js
//统一暴露
let school = '北大'
function findJob(){
console.log('找工作')
}
export {school,findJob}
复制代码
//m3.js
//默认暴露
export default{
school: '北大',
change: function(){
console.log('改变你')
}
}
复制代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ES6 模块化</title>
</head>
<body>
<script type="module">
//1.通用的导入方式
//引入 m1.js 模块内容
import * as m1 from "./src/js/m1.js"
//引入 m2.js 模块内容
import * as m2 from "./src/js/m2.js"
//引入 m3.js 模块内容
import * as m3 from "./src/js/m3.js"
console.log(m3)
m3.default.change()
//2.解构赋值形式
import {school, teach} from "./src/js/m1.js"
import {school as beida, findJob} from "./src/js/m2.js"
import {dafault as m3} from "./src/js/m3.js"
//3.简编形式 针对默认暴露 (常用)
import ms from "./src/js/m3.js"
console.log(m3)
m3.change()
</script>
</body>
</html>
复制代码
ES7
1.includes 和 ** 幂运算
// indexOf 返回的是数字
const mingzhu = ['西游记','红楼梦','三国演义','水浒传']
//判断
console.log(mingzhu.includes('西游记')) //true
console.log(mingzhu.includes('金瓶梅')) //false
// **
console.log(2 ** 10) //1024
console.log(Math.pow(2,10)) //1024
复制代码
ES8
1.async 和 await
async 和 await 两种语法的结合可以让异步代码像同步代码一样。
2.async 函数
1)async 函数的返回值为promise对象
2)promise 对象的结果由 async 函数执行的返回值决定
//async 函数
async function fn(){
//返回一个字符串
// return '尚硅谷'
// 返回的结果不是一个 Promise 类型的对象,返回的结果就是成功Promise 对象
// return
//抛出错误,返回的结果是一个失败的Promise
// throw new Error(' 出错啦!')
//返回的结果如果是一个Promise 对象
return new.Promise((resolve,reject)=>{
// resolve( '成功的数据' )
reject("失败的错误" )
})
}
const result = fn()
//调用then 方法
result.then(value => {
console.log(value)
}, reason => {
console.warn(reason)
})
复制代码
3.await 表达式
1)await必 须写在async函数中
2)await 右侧的表达式- -般为promise对象
3)await 返回的是promise成功的值
4)await 的promise失败了,就会抛出异常,需要通过try..catch捕获处理
//创建 promise 对象
const p = new Promise((resolve,reject)=>{
//resolve('用户数据')
reject('出错啦!')
})
// await 要放在 async 函数中
async function main(){
try{
let result = await p
console.log(result)
}catch(e){
console.log(e)
}
}
//调用函数
main()
复制代码
4.async 和 await 结合读取文件
//1.引入fs模块
const fs = require('fs')
//读取为学
function readWeiXue(){
return new Promise((resolve,reject)=>{
fs.readFile("./resources/为学.md",(err,data)=>{
//如果成功
if(!err) resolve(data)
//如果失败
reject(err)
})
})
}
function readChaYangShi(){
return new Promise((resolve,reject)=>{
fs.readFile("./resources/插秧诗.md",(err,data)=>{
//如果成功
if(!err) resolve(data)
//如果失败
reject(err)
})
})
}
function readGuanShu(){
return new Promise((resolve,reject)=>{
fs.readFile("./resources/观书有感.md",(err,data)=>{
//如果成功
if(!err) resolve(data)
//如果失败
reject(err)
})
})
}
//声明一个 async 函数
async function main(){
//获取为学内容
let weixue = await readWeiXue()
//获取插秧诗内容
let chayang = await readChaYangShi()
//获取观书有感内容
let guanshu = await readGuanShu()
console.log(weixue.toString())
console.log(chayang.toString())
console.log(guanshu.toString())
}
main()
复制代码
5.async 和 await 结合封装AJAX请求
//发送 AJAX 请求,返回的结果是 Promise 对象
function sendAJAX(url){
return new Promise((resolve,reject)=>{
//1.创建对象
const x = new XMLHttpRequest()
//2.初始化
x.open('GET', url)
//3.发送
x.send()
//4.事件绑定
x.onreadystatechange = function(){
if(x.readyState === 4){
if(x.status >=200 && x.status <300){
//成功
resolve(x.response)
}else{
//失败
reject(x.status)
}
}
}
})
}
//Promise.then 方法测试
sendAJAX('https://api.apiopen.top/getJoke').then(value=>{
console.log(value)
},reason=>{})
//async 与 await 测试
async function main(){
let reasult = await sendAJAX('https://api.apiopen.top/getJoke')
//再次测试
let tianqi = await sendAJAX('http://www.tianqiapi.com/index/doc?version=day')
console.log(reasult)
}
main()
复制代码
6.ES8对象方法扩展
//声明对象
const school = {
name: '北大',
cities: ['北京','上海','深圳'],
xueke: ['前端','Java','大数据','运维']
}
//获取对象所有的键
console.log(Object.keys(school))
//获取对象所有的值
console.log(Object.values(school))
//entries
console.log(Object.entries(school))
//创建Map
const m = new Map(Object.entries(school))
console.log(m)
//对象属性的描述对象
conosle.log(Object.getOwnPropertyDescriptors(school))
const obj = Object.create(null,{
name:{
//设置值
value: '北大',
//属性特性
writable: true,
configurable: true,
enumerable: true
}
})
复制代码
ES9
1.对象的 rest 参数和扩展运算符
Rest参数与spread 扩展运算符在ES6中已经引入,不过ES6 中只针对于数组.
在ES9中为对象提供了像数组样的rest参数和扩展运算符
//rest参数
function connect({host, port, ...user}){
console.log(host)
console.log(port)
console.log(user)
}
connect({
host: '127.0.0.1',
port: 3306,
username: 'root',
password: 'root',
type: 'master'
})
//扩展运算符 对象合并
const ski1lOne = {
q: '天音波'
}
const skillTwo = {
W: '金钟罩'
}
const skillThree = {
e: '天雷破'
}
const skillFour = {
r: '猛龙摆尾'
}
const mangseng = {...skillOne, ...skillTwo, ... skillThree, ...skil1Four}
console.log(mangseng)
复制代码
2.正则扩展-命名捕获分组
//声明一个字符串
let str = '<a href="http://www.baidu.com">百度</a>'
// 提取 url 与标签文本
const reg = /<a = href="https://juejin.cn/post/(.*)">(.*)<\/a>/
//执行
const result = reg.exec(str)
console.log(result[1])
console.log(result[2])
//命名捕获分组 比数字下标更容易维护
const reg = /<a = href="https://juejin.cn/post/(?<url>.*)">(?<text>.*)<\/a>/
const result = reg.exec(str)
console.log(result.groups.url)
console.log(result.groups.text)
复制代码
3.正则扩展-反向断言
//声明字符串
let str = 'JS5211314你知道么555啦啦啦'
//正向断言
// const reg = /\d+(?=啦)/
// const result = reg.exec(str)
//反向断言
const reg = /(?<=么)\d+/
const result = reg.exec(str)
console.log(result)
复制代码
4.正则扩展-dotAll模式
//dot . 元字符 除换行符以外的任意单个字符
let str =`
<ul>
<li>
<a>肖生克的救赎</a>
<p>上映日期: 1994-09-10</p>
</li>
<li>
<a>阿甘正传</a>
<p>上映日期: 1994-07-06</p>
</li>
</ul> `
//声明正则
const reg = /<li>\s+<a>(.*?)<\/a>\s+<p>(.*?)<\/p>/
const reg = /<li>.*?<a>(.*?)<\/a>.*?<p>(.*?)<\/p>/gs
//执行匹配
//const result = reg.exec(str)
let result
let data = []
while(result = reg.exec(str)){
data.push({title: result[1], time: result[2]})
}
console.log(data)
复制代码
ES10
1.对象扩展方法Object.fromEntries 将二维数组转为对象
//二位数组
const result = Object.fromEntries([
['name','北大'],
['xueke','Java,大数据,前端,云计算']
])
//Map
const m = new Map()
m.set('name','beida')
const result = Object.fromEntries(m)
//Object.entires ES8 将对象转为二维数组
const arr = Object.entires({
name: '北大'
})
console.log(arr)
复制代码
2.字符串扩展方法trimStart 与 trimEnd
//trim 清除字符串左右空白
let str = ' iloveyou '
console.log(str)
console.log(str.trimStart()) //清除字符串左空白
console.log(str.trimEnd()) //清除字符串右空白
复制代码
3.数组扩展方法 flat 和 flatMap
//flat 平
//将多维数组转化为低维数组
// const arr = [1,2,3,4,[5,6]]
// const arr = [1,2,3,4,[5,6,[7,8,9]]]
//参数为深度 是一个数字
// console .1og(arr.flat(2))
//flatMap 如果返回值是多维数组,可以对其降维
const arr = [1,2,3,4]
const result = arr.flatMap(item => [item * 10])
console.log(result);
复制代码
4.Symbol.prototype.description
//创建 Symbol
let s = Symbol('北大')
console.log(s.description) //北大
复制代码
ES11
1.类的私有属性
class Person{
//公有属性
name;
//私有属性
#age;
#weight;
//构造方法
constructor(name, age, weight){
this.name = name
this.#age = age
this.#weight = weight
}
//内部访问
intro(){
console.log(this.name)
console.log(this.#age)
console.log(this.#weight)
}
}
//实例化
const girl = new Person('小红',18,'45kg')
console.log(girl.name)
console.log(girl.#age) //无法通过实例化对象进行访问
console.log(girl.#weight)
复制代码
2.Promise.allSettled
//声明两个promise对象
const p1 = new Promise((resolve, reject)=>{
setTimeout(()=>{
resolve( '商品数据- 1');
}, 1000)
})
const p2 = new Promise((resolve, reject)=>{
setTimeout(()=>{
resolve('商品数据- 2');
// reject('出错啦!');
}, 1000 )
})
//调用allsettled 方法 始终返回成功的promise
// const result = Promise.allSettled([p1, p2]);
// all方法 都成功才返回成功的promise
// const res = Promise.all([p1, p2]);
console.log(res)
复制代码
3.String.prototype.matchAll
let str =`
<ul>
<li>
<a>肖生克的救赎</a>
<p>上映日期: 1994-09-10</p>
</li>
<li>
<a>阿甘正传</a>
<p>上映日期: 1994-07-06</p>
</li>
</ul> `
//声明正则
const reg = /<li>.*?<a>(.*?)<\/a>.*?<p>(.*?)<\/p>/gs
//调用方法
const result = str.matchAll(reg)
const arr = [...result]
console.log(arr)
复制代码
4.可选链操作符
// ?.
function main(config){
// const dbHost = config && config.db && config.db.host
const dbHost = config?.db?.host
console.log(dbHost)
}
main({
db:{
host: '192.168.1.100',
username: 'root'
},
cache: {
host: '192.168.1.200',
username: 'admin'
}
})
复制代码
5.动态import
//hello.js
export function hello(){
alert('Hello')
}
复制代码
//app.js
const btn = document.getElementById('btn')
btn.onclick = function(){
//调用import函数进行动态导入模块
import('./hello.js').then(module=>{
module.hello()
})
}
复制代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>动态import加载</title>
</head>
<body>
<button id="btn"></button>
<script src="./js/app.js" type="module"></script>
</body>
</html>
复制代码
6.BigInt
// 大整形
//let n = 521n
// console.1og(n, typeof(n))
//函数
//let n = 123
// console.log(BigInt(n))
// console.log(BigInt(1.2)) //报错
//大数值运算
let max = Number.MAX_SAFE INTEGER //最大安全整数
console.log(max)
console.1og(max + 1)
console.1og (max + 2) //运算异常
console.log(BigInt(max))
console.1og(BigInt(max) + BigInt(1))
console.log(BigInt(max) + BigInt(2))
复制代码
7.绝对全局对象globalThis
无论在什么环境下,始终指向window