004ES6+

ES6+

var、let、const

var

// 1
function ff() {
	console;log(a)  // undefined
	var a = 1; // a: ff
}
ff()

// 2 自动变量类型提升成全局变量
var b = 1  // b = 1; window.b = 1;

// 3 多个(自动提升成一个唯一的i => 012345)  window.i === 5
var lis = document.querySelectorAll('li');

for(var i = 0; i < lis.length; i++){
	lis[i].onclick = function() {
		alert(i)  // i === 5
	}
}

// 解决方式
// 1、自执行函数(闭包)
for(var i = 0; i < lis.length; i++){
	(function(n) {
        lis[n].onclick = function() {
            alert(n)  // n 分别为0、1、2、3、4
        }
	})(i)
}

// 2、给元素绑定值
for(var i = 0; i < lis.length; i++){
	lis[i].id = i;
	lis[i].onclick = function() {
		alert(this.id)  // 分别为0、1、2、3、4
	}
	
}

// 3、var => let
for(let i = 0; i < lis.length; i++){
	(function(n) {
        lis[n].onclick = function() {
            alert(n)  // n 分别为0、1、2、3、4
        }
	})(i)
}

let

顶部声明不会提升为全局,块级作用域(唯一)

语法上不允许多次声明同名变量

值可以改变,且可以二次赋值

let b = 2;
// window.b  // undefined 不会全局

let n = 99;
if(true) {
	let n = 3;
	console.log(n) // 3 就近原则
}

let n2 = 1;
if(true) {
	// let 声明的变量属于块钱作用域
	// 编辑期将其解析 不在向上查找
	// 在初始化之前,不能访问该变量: 临时性死区
	console.log(n2) // 报错
	let n2 = 100;
}

const

值不能二次改变,并且必须一次性赋值

const PI = '3.1415926'

const obj = {}; // 存储的地址
obj.a = 1;
obj.b = 2;

箭头函数

箭头函数不能作为构造函数

this是根据上线文固定的,而不是动态的this对象决定

不能被call bind apply 改变指向

// 多个参数
let ff1 = (a,b) => {
	console.log('xxx');
	return 1;
}

// 一个参数
let ff2 = a => {
	console.log('xxx');
	return 2;
}

// 一行代码就是返回值
let ff3 = a => a;

// 返回值是一个对象
let ff2 = a => ({});

// 复杂写法
// 看箭头+左边参数 右侧是返回值或者函数体
let aa = n => n => (n, m) => (n, m) => n  // aa 是一个函数

解构赋值

左边解构:解析解构

右边赋值

对象(按名称)

let {a,xxx} = {a:1, b:2}
console.log(a,xxx) // 1 undefined

// :(+别名)取别名(a不存在只是一个标识)
let {a: asA} = {a:1, b:2}
console.log(asA) // 1

// :(+结构)
let {obj: {b}} = {obj: {a:1, b:2}}
console.log(b) // 2

数组(按顺序)

let [a,b,c] = [1,2,3]
console.log(a,b,c)  // 1 2 3

// 不可取别名

// 跳着获取元素
let [,b1,c1] = [1,2,3]
console.log(b1,c1)  // 2 3

函数参数解构

function parseProp({client}) {
	return client
}

函数默认值

优先已传递进来的为准,没有传递填充默认值

// 参数默认值
function add(a=0,b=0) {
	return a + b
}

组合运用

const fun = ({x=1, y} = {y:2}) => {
	// 隐性存在
	// 没有传递参数: Object.assign(形参, 默认值对象)
	// 传递参数: 以形参为主
	console.log(x,y)  
}
fun()  // 1 2 // 二合一 以默认值为主

fun({x: 1}) // 1 undefined  // 以形参为主

展开运算符

便于代码复用

属于浅拷贝 大规模使用时需要注意引用数据类型的深拷贝

let arr = [1,2,3]
let arr2 = [0, ...arr]

let obj = {name: '张三’, age: 19}
let obj2 = {...obj, address: ''}

// 注意: 属性覆盖  先展开后覆盖
let obj3 = {
	...obj,
	name: '李四'
}

// ...args:是一个数组  可以接受到剩余参数

function add(...args) {
	return args.reduce((sum, n) => {
		return sum + n
	}, 0)
}

arr(1,2,3,4,5,6,7,8,9)

无限平铺

let arr = [1,[2,[3,[6,[7]]]], 4,5]

arr.flat() // 返回一个新数组 [1, 2, [3,[6,[7]]], 4, 5]  只展开一层

arr.flat(Infinity) // 返回一个新数组 [1, 2, 3, 6, 7, 4, 5]  无限展开

// 利用...平铺
function myFlat(arr) {
	// 判断元素是否时数组 不是结束循环
	// while(arr.some((ele) => {
	// 	return Array.isArray(ele)
	// })) {
	// 	arr= [].concat(...arr)
	// }
	
	// 简化
	while(arr.some(Array.isArray)) {
		arr= [].concat(...arr)
	}
	
	return arr;
}

const newArr2 = myFlat(arr2);

可选链

// 对象数组可选链
let id = res?.data?.info?.[4]?obj?.id

// 方法可选链
function error(fn) {
	console.log('错误信息')
	fn?.('回调信息')
}

error()
error((info) => console.log('回调执行'))

空值合并(??)

默认数据的填充,区分隐式数据类型数据转换

主要针对于null undefined

console.log(null ?? '后')  // 后
console.log(undefined ?? '后')  // 后
console.log(0 ?? '后')  // 0
console.log('' ?? '后')  // ''

console.log(null || '后')  // 后
console.log(undefined || '后')  // 后
console.log(0 || '后')  // 后
console.log('' || '后')  // 后

Map Set WeakMap WeakSet

具备优化性能的算法存储数据 同时自带去重功能

Set

单列的(key === value)

let arr = [1,2,3,2,2,3,1,213,43214,1,1,3,2]

// 1.直接通过数组构造(数组去重,但不会排序)
let set = new Set(arr)

// 2.添加数据(可以为任意数据类型 且自带去重)
set.add(8);
set.add({});  // 引用数据类型 堆  对应一个地址

let obj = {}
set.add(obj)

// 3.转换成数组  (元素不会存在深拷贝)
let arr2 = Array.from(set)

// 4.长度(size)
console.log(set.size)

// 5.删除(delete)
set.delete(null)

set.delete({}) // 无法删除  生成新的 堆 及 新地址

set.delete(obj) // 删除obj  删除需要先声明在删除

// 6.是否存在(has)
console.log(set.has(1))

// 7.(keys)  返回 Iterator 迭代器
set.keys()

// 8.(values)  返回 Iterator 迭代器
set.values()

// 9.(entries)  // Map = keys + values  返回 Iterator 迭代器
set.entries()

// 10.(forEach)
set.forEach((val,key) => {
	console.log(val, key)
})

// 11.清空所有(clear)
set.clear()
数组去重排序
const killDup = (arr) => {
	return Array.from(new Set(arr))
}

// 数组去重
let arr = killDup([5,4,4,3,2,1,7,8,9,6,5,3,2,4])

// 数组排序
arr.sort(); // 只能针对于10以内的数据排序

// 如果 compareFn(a,b)  return值 >0  b在a之前
// 如果 compareFn(a,b)  return值 <0  a在b之前
// 如果 compareFn(a,b)  return值 =0  a、b相对位置不变
arr.sort((a,b) => {
	// 数组正序  判断a是否大于b => a > b => b,a
	// return a - b;  
	// 数组逆序  判断b是否大于a => b > a  => b,a
	return b - a;  
})

Map

// 1.创建
let obj = {name: 'zs'}
let arr = [['a', 1], [obj, 2]]
let map = new Map(arr)

// 2.添加(set)
map.set('b', 3)
map.set('c', 4)

// 3.判断(has)
console.log(map.has(obj))

// 4.长度(size)
console.log(map.size())

// 5.删除(delete)

// 6、转换
let arr2 = Array.from(map)

// 7.(keys)  返回 Iterator 迭代器
map.keys()

// 8.(values)  返回 Iterator 迭代器
set.values()

// 9.(entries)  // Map = keys + values  返回 Iterator 迭代器
map.entries()

// 10.(forEach)
map.forEach((val,key) => {
	console.log(val, key)
})

// 11.清空所有(clear)
map.clear()

数组:计算机基础中 数组是一块联系的空间(查找快),计算机开辟连续空间【new Array(空间大小) 】增加删除后改变空间大小【再次开辟新空间,拷贝数据】

Map底层实现
cosnt mapSize = 8;
function MyHashMap() {
	this.initStore();
}

MyHashMap.prototype.initStore = function() {
	this.store = new Nrray(mapSize);
	for(let i = 0; i < mapSize; i++) {
		this.store[i] = {
			next: null
		}
	}
}

MyHashMap.prototype.hash = function(n) {
	return n % mapSize; // 取余
}

MyHashMap.prototype.has = function(key) {
	return !!this.get(key)
}

MyHashMap.prototype.get = function(key) {
	// 根据key计算房间号
	let index = this.hash(key);
	// queue 对象
	let queue = this.store[index];
	
	while(queue.next) {
		if(queue.key === key) {
			return queue.val;
		} else {
			// 指针下移
			queue = queue.next
		}
	}
	
	return undefined;
}

// 存储数据
MyHashMap.prototype.set = function(key, val) {
	// 根据key计算房间号
	let index = this.hash(key);
	// queue 对象
	let queue = this.store[index];
	
	// 找后面next是否有数据,对比key,如果满足则覆盖
	// 链表
	while(queue.next) {
		if(queue.next.key === key) {
			queue.next.val = val; // 覆盖
			return;
		} else {
			// 再看下一个
			queue = queue.next
		}
	}
	
	// 赋值
	queue.next = {
		next: null,
		key,
		val
	}
}

var map = new MyHashMap()
map.set(1, 'a')
map.set(2, 'b')
map.set(3, 'c')
map.set(9, 'd')
console.log(map)
console.log(map.get(9))
console.log(map.has(2))

WeakMap

相对于Map无遍历;key只能使用引用数据类型(对象)

let map = new WeakMap();

//增
let obj = {}
map.set(obj, 1)

// 取
console.log(map.get(obj))

// 判
console.log(map.has(obj))

// 删
map.delete(obj)

// 无遍历

WeakSet

key只能使用引用数据类型 (对象)

let set = new WeakSet();

// 增
let obj = {}
set.add(obj)

// 不可以单个获取值,可转成数组

// 判
console.log(set.has(obj))

// 删
set.delete(obj)

// 无遍历

强引用

Map、Set

functin Green() {}

let arr = new Array(20000).fill(null),map(e => new Green())

let map = new WeakMap();

// WeakMap的key只能使用引用数据类型

let obj = {};  //引用计数1

map.set(obj,arr);  // 不会引用计数+1

obj = null  // 引用计数-1

// 释放arr
arr = null;  // 引用计数-1
functin Green() {}

let arr = new Array(20000).fill(null),map(e => new Green())

// Map的key可以使用引用数据类型

let map = new Map();

let obj = {};  //引用计数1

map.set(obj,arr);

// 附加处理map内的强引用
map.delete(obj);

obj = null  // 引用计数-1

// 释放arr
arr = null;  // 引用计数-1

弱引用

WeakMap、WeakSet

functin Green() {}

let arr = new Array(20000).fill(null),map(e => new Green())

let map = new WeakMap();

// WeakMap的key只能使用引用数据类型

let obj = {};  //引用计数1

map.set(obj,arr);  // 不会引用计数+1

obj = null  // 引用计数-1

// 释放arr
arr = null;  // 引用计数-1

WeakRef(了解)

能不使用尽量不要使用

functin Green() {}

let arr = new Array(20000).fill(null),map(e => new Green())

// 强引用
// let arr2 = arr;  // 引用计数+1
// arr2 = null;

// 弱引用
let ref = new WeakRef(arr);  // 引用计数不存在+1

// GC垃圾回收一旦执行获取的值deref就是undefined
console.log(ref.deref().length)

arr = null

手写深拷贝优化

let obj1 = {
	arr: [1,2,3],
	arrOfObjs: [{c: 5}, {d: 6}],
	obj: {val: 4},
	fn: function() {
		return 5;
	},
	set: new Set(),
	map: new Map(),
	nul: null,
	undef: undefined,
};

// 环形对象
var obj2 = {
	to: obj1
}
obj1.to = obj2

// 处理环形对象(全局性对象统一缓存)
var cache = new WeakMap()

var cloned = deepClone(obj1);

function deepClone(obj) {
	if(typeof obj !== 'object' || !obj){
		// 处理基本的数据类型 undefined null function
		retutn obj;
	} 
	
	if(cache.has(obj)){
		return cache.get(obj)
	}
    
    let tmp;
    if (obj instanceof Map) {
		tmp = new WeakMap();
		cache.set(obj,tmp);
		obj.forEach((val, key) => {
			tmp.set(deepClone(key), deepClone(val))
		})
	} else if (obj instanceof Set) {
		tmp = new Set();
		cache.set(obj,tmp);
		obj.forEach((val) => {
			tmp.add(deepClone(val))
		})
	} else if (obj instanceof RegExp || obj instanceof Date) {
		tmp = new obj.constructor(obj);
		cache.set(obj,tmp);
	}  else {
		// 处理引用数据类型  数组 || 对象 及 其他
		tmp = new obj.constructor();
		cache.set(obj,tmp);
        for(var key in obj){
        	tmp[key] = deepClone(obj[key]);
        }
	}
	
	 return tmp;
}

Symbol常量

toStringTag

底层类型标注

function Person(){}

let obj = new Person()

console.log(Object.prototype.toStrig.call(obj))  // [object Object]
console.log(Object.prororype.toString.call({}))  // [objcet Object]

functin Person1(){}
// 底层类型标注
Person1.prototype[Symbol.toStringTag] = Person.name
let obj1 = new Person();
console.log(Object.prototype.toStrig.call(obj1))  // [object Person] 

toPrimitive

引用数据类型在做基本数据类型转换时的底层行为 例如 + - * %

let obj = {name: 'zhangsan'};
console.log(obj - 1) // NaN

let obj1 = {name: 'lisi', age: 36};
obj1.__protp__[Symbol.toPrimitive] = function(){
	// return 99;
	return this.age
}

// consloe.log(obj - 2) // 97

// consloe.log(obj - 2) // 34

iterator

可迭代

let map = new Map([['a': 1], ['b': 2]])

let obj = Object.fromEntries(map);  // Map转Object
console.log(obj);

obj.c = 3;

// let map2 = new Map(obj);  // error: obj is not iterable
// for(let val of obj) {
//	console.log(val)
//} // error: obj is not iterable

// 解决方式:
obj.__proto__[Symbol.iterator] = function() {
	let entries = Object.entries(this) //  Object转Map  this为{a: 1, b: 2, c: 3}
	let len = entries.length
	
	let index = 0
	
	return {
		next: () => {
			let done = index >= entries.length
			let value = entries[index];
			index++;
		
			return {
				value,
				done
			}
		}
	}
}

for(let val of obj) {
	console.log(val)
}

generator(了解)

迭代器(过渡)

// 生成器的声明
function* gen() {
	console.log('abc')
	
	// 礼让 => 异步
	let res = yield 'eee'
	
	console.log('1111', res)
}

// 获取生成器对象
let generator = gen()

console.log(generator)

let res = generator.next()  // 代码执行 礼让  abc
generator.next(res.value)  // 将礼让时的值传入 再次执行  1111 eee

Promise

回调函数

function req(fn) {
	setTime(() => {
		// 数据回来
		let data = 123;
		fn(data) // 回调
	}, 1000)
}

req((data) => {
	console.log(data)
});
回调函数(嵌套)地狱
function req(fn) {
	setTime(() => {
		// 数据回来
		let data = 123
		fn(data) // 回调
	}, 1000)
}

req((data) => {
	console.log(data)
	req((data1) => {
		console.log(data1)
		req((data2) => {
			console.log(data2)
		});
	});
});
解决回调函数地狱

通过异步容器管理异步执行顺序

使代码更为简洁

function req() {
	// resolve 解决
	// reject 拒绝
    return new Promise((resolve, reject)) => {
        setTime(() => {
            // 数据回来
            let data = Math.random()
            resolve(data)
        }, 1000)
    }
}

// 通过promise实例.then((res) => {})
req() // 请求1
    .then(res => {
        console.log(res) // 响应1
        return req(); // 请求2
    })
        .then(res2 => {
            console.log(res2) // 响应2
            return req(); // 请求2
        })
             .then(res3 => {
                console.log(res3) // 响应3
            })

状态及后续

// pending(待发) <=  初始态
let p1 = new Promise((resolve, reject) => {})

// fulfilled(已满足)  <=  resolve
let p2 = new Promise((resolve, reject) => {
	resolve('123')
})
    .then(res => {
        console.log(res)
    })  // 处理完成后 仍然处于fulfilled状态
    .finally(() => {
    	console.log('无论如何最终将会执行')
    })

// rejected(已拒绝)  <=  reject
let p3 = new Promise((resolve, reject) => {
	reject('err')
})
    .catch(err => {
        console.log(err)
    })  // 处理完成后 变成fulfilled状态

// 实现中可以多组then 对应一个catch
// then接在fulfilled状态后

new Promise((resove, reject) => {
	resove(123)
})
    .then(res123 => {
		console.log(res123);
		return new Promise((resove, reject) => {
			resove(456)
		})
    })
    	.then(res456 => {
    		console.log(res456)
    	})

PromiseApi

function req() {
    return new Promise((resolve, reject)) => {
        setTime(() => {
            let data = Math.random()
            if(data < 0.5){
            	reject('req失败了')
			} else {
				resolve(data)
			}
        }, 1000)
    }
}

function req1() {
    return new Promise((resolve, reject)) => {
        setTime(() => {
            let data = Math.random()
            if(data > 0.5){
            	reject('req1失败了')
			} else {
				resolve(data)
			}
            resolve(data)
        }, 1000)
    }
}

// 1、Promise.all()
// 如果多个请求,任意一个失败则失败
Promise.all([
	req(),
	req1(),
]).then(([res, res1]) => {  // 返回的是一个数组 进行解构
	// 数据响应
	console.log(res, res1)
}).catch((err) => {
	console(err)
})

// 2、Promise.race()
// 获取的是第一个响应的结果
Promise.race([
	req(),
	req1(),
]).then((res) => {
	// 数据响应
	console.log(res)
}).catch((err) => {
	console(err)
})

// 3、Promise.resove()
// 直接创造 fulfilled 状态
const fulfilledPromise = Promise.resove('aaa')
fulfilledPromise.then(res => {console.log(res)})

// 4、Promise.reject()
// 直接创造 rejected 状态
const rejectedPromise = Promise.reject('err')
rejectedPromise.catch(err => {console.log(err)})

async await

// 输出结果 1 3 5 2 4

async function asyncFn() {
	console.log(3)
	await new Promise(res => {
		console.log(5)
		res()
	});
	// 如果Promise不调用res 则不会执行console.log(4)
	// 等同于.then()里面的代码
	console.log(4)
}

console.log(1)
asyncFn()
console.log(2)

优雅处理async await

try catch 处理
function req() {
    return new Promise((resolve, reject)) => {
        setTime(() => {
            let data = Math.random()
            if(data < 0.5){
            	reject('req失败了')
			} else {
				resolve(data)
			}
        }, 1000)
    }
}

async function run() {
    try{
        let res = await req()
        console.log(res)
    }catch(e){
		console.log(e)
    }finally(){
    	console.log('最终')
    }
}

run()
中间层处理
function req() {
    return new Promise((resolve, reject)) => {
        setTime(() => {
            let data = Math.random()
            if(data < 0.5){
            	reject('req失败了')
			} else {
				resolve(data)
			}
        }, 1000)
    }
}

function pretty(promise) {
	// 参数错误优先
	return promise
        .then(res => {
            return [undefined, res]
        })// 处理完成后变成 fulfilled 状态
        .catch(err => {
			return [err, undefined]
        })// 处理完成后变成 fulfilled 状态
}

async function run() {
	let [err, data] = await pretty(req())
	if(err){
		console.log('数据错误了')
		return
	} else {
		console.log(data)
	}
}

run()
集中处理
function req() {
    return new Promise((resolve, reject)) => {
        setTime(() => {
            let data = Math.random()
            if(data < 0.5){
            	reject('req失败了')
			} else {
				resolve(data)
			}
        }, 1000)
    }
}

async function run() {
	var res = await req()
	console.log(res)
}

run()

window,addEventListener('unhandledrejection', (err) => {
	err.preventDefault()
	console.log(err.reason)
})

forEach存在的坑

let arr = [1,2,3,4,5, {name: 'zhangsan'}]

function req(n) {
    return new Promise((resolve, reject)) => {
        setTime(() => {
			resolve(n)
        }, 1000)
    }
}

// 存在调用时间不会每隔1秒执行一次
// arr.forrEach(async ele => {
//	await req(ele)
// })

// 解决方式重写forEach
// 实现forEach覆盖
Array.prototype.forEach = async function(fn){
	if(typeof fn !== 'function') throw new Errer('不是函数')
	
	if(!Array.isArray(this))throw new Errer('this不是数组')
	
	for(let i = 0, len = this.length; i < len; i++){
		// this, ele, index, newArr
		await fn.call(this, this[i], i, this)
	}
}

arr.forrEach(async (ele, index, newArr) => {
	await req(ele)
})
  • 11
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值