let和const
应用 var 带来的问题
var 净化全局变量
var a=1;console.log(window.a)
var 会使变量晋升
console.log(a) // undefinedvar a=1;
var 能够被反复申明
var a=1;var a=2;var a=3;
var 作用域问题
全局作用域
{ var a=1;}console.log(a) // 1{ let b=2;}console.log(b) // b is not defined
函数作用域
for(var i=0;i<3;i++){ setTimeout(()=>console.log(i),0) // 3,3,3}for(let i=0;i<3;i++){ setTimeout(()=>console.log(i),0) // 0,1,2}
const 常量
const
指向地址不变
开展运算符
合并对象或数组
合并数组
let a=[0,1];let b=[2,3];console.log([...a,...b]) //[0, 1, 2, 3]
合并对象
合并对象要辨别是深拷贝还是浅拷贝,开展运算符只拷贝对象一层,属于浅拷贝
let team={name:"Lakers",location:{city:"Los Angeles"}};let player=["LeBron","Davis"];let kuzma = {age:25};let coach = {name:"Frank Vogel",age:47};let Lakers = { ...team, ...coach, player:[...player,kuzma]}team.name="change"; // Lakers 批改失败,浅拷贝team.location.city = "change"; // Lakers 批改胜利,援用地址未变console.log(Lakers)
实现深拷贝
1、持续开展
let Lakers = { team:{ ...team, location:{...team.location} }, ...coach, player:[...player,kuzma]}
2、对象转字符串再转对象,这种形式有个缺点,会疏忽掉值为undefined
的属性
Lakers = JSON.parse(JSON.stringify(Lakers))
3、实现深拷贝办法
// 判断类型:typeof、instanceof、Object.prototype.toString.call、constructotfunction deepClone(obj){ // 不是对象间接返回 if(obj == null) return obj; if(obj instanceof Date) return new Date(obj); if(obj instanceof RegExp) return new RegExp(obj); if(typeof obj !== "object") return obj; // 可能是数组或对象 let cloneObj = new obj.constructor; for(let key in obj){ if(obj.hasOwnProperty(key)){ // 递归赋值 cloneObj[key] = deepClone(obj[key]); } } return cloneObj}
Set 和 Map
Set
let s1 = new Set([0,1,2,0,2]);let s2 = new Set([2,3,3,4,5]);// 并集function union(){ let merge = [...s1,...s2]; return [...new Set(merge)]}// 交加function intersection(){ return [...s1].filter(item=>s2.has(item));}// 差集 s1=>s2function diff(){ return [...s1].filter(item=>!s2.has(item));}
Map
Map
有 key
值,不能反复,WeakMap
的 key
必须是对象类型
let wm=new WeakMap();let obj = {name:"124"};wm.set(obj,"test");obj = null;console.log(wm) // 清空obj,这个空间依然存在m/* WeakMap* [[Entries]]* 0: {{name: "124"} => "test"}*/
利用WeakMap
优化 深拷贝函数:
function deepClone(obj,hash = new WeakMap()){ if(obj == null) return obj; if(obj instanceof Date) return new Date(obj); if(obj instanceof RegExp) return new RegExp(obj); if(typeof obj !== "object") return obj; // 如果是对象并存在weakMap中,阐明拷贝的对象曾经存在了,间接返回 if(hash.has(obj)) return hash.get(obj); let cloneObj = new obj.constructor; // 保留拷贝的对象到WeakMap中 hash.set(obj,cloneObj); for(let key in obj){ if(obj.hasOwnProperty(key)){ cloneObj[key] = deepClone(obj[key],hash); } } return cloneObj}
Object.defineProperty
对象自带的 getter
和 setter
:
let obj = { value:"124", get name(){ console.log("get") return this.value }, set name(val){ console.log("set") this.value = val; }}console.log(obj.name)obj.name="test";console.log(obj.name)
利用 Object.defineProperty
实现数据劫持
let update = () => console.log("update");let team = { name: "Lakers", player:["lbj","ad"], location: { city: "Los Angeles" }};observer(team);function observer(obj) { if(typeof obj !== "object") return obj; for(let key in obj) { defineReactive(obj, key, obj[key]); }}function defineReactive(obj, key, value) { observer(value); Object.defineProperty(obj,key,{ get(){ return value }, set(newVal){ if(newVal === value) return; update(); observer(newVal); // 新值也有可能是对象 value = newVal } })}// 数组操作无奈劫持,重写无奈劫持的数组办法const Methods = ["push","pop","shift","unshift","slice","sort","reverse"];Methods.forEach(method=>{ // 面向切面开发,装璜器 const oldMethod = Array.prototype[method]; Array.prototype[method] = function(){ update(); oldMethod.apply(this,arguments) }});team.name="la";team.location.city = "change";team.player.push("kz")
箭头函数
箭头函数没有 this
和 arguments
Proxy
- Object.defineProperty 劫持不到数组的更新(push、pop、shift、unshift)
- Proxy 能够监测到数组和对象的变动
- Proxy 监测数组变动时,要留神数组长度的变动也会被监测到,这时手动扭转数组会出问题
let update = ()=>console.log("update");let arr = [1,2,3];// Proxy 能够监测到数组和对象的变动// 数组的变动会先扭转数组的内容,还会扭转数组的长度let proxy = new Proxy(arr,{ set(target,key,value){ // 不要手动操作数组,因为数组变动时,可能调用push或pop扭转数组长度,这时key值会出问题 if(key == "length") return true; update(); return Reflect.set(target,key,value); }, get(target,key){ return Reflect.get(target,key); }})proxy.push("4");console.log(proxy)
数组罕用办法
- es5 forEach reduce map filter some every
- es6 find findIndex
- es7 includes
reduce 常见用法
求和
// 购物车let cart = [ {price:10,count:2}, {price:20,count:3}, {price:19.9,count:2}, {price:14.5,count:1}];// 求购物车总价格let totalPrice = cart.reduce( (total,item)=>total+item.price*item.count,0);
合并数据
let keys = ["name","age"];let value = ["kobe",18];let result = keys.reduce( (obj,key,index)=>{ obj[key]=value[index] return obj; },{});
compose 办法
function sum(a,b) { return a+b};function toUpper(str){ return str.toUpperCase();}function log(target){ console.log(target)}compose(sum,toUpper,log)("chen","wl");function compose(...middlears){ //return middlears.reduce((a,b)=>(...args)=>b(a(...args))) return (...args)=>{ let fn = middlears.shift(); middlears.reduce((a,b)=>{ return b(a) },fn(...args)); }}
reduce
简略实现
Array.prototype.reduce = function(fn,prev){ let target = deepCopy(this); let total = prev || target.shift(); target.forEach((next,i)=>{ total = fn(total,next,i,target); }); return total;}let result = [1,2,3,4].reduce((a,b)=>a+b);console.log(result)function deepCopy(obj){ if(obj == null) return obj; if(typeof obj !== "object") return obj; let newObj = new obj.constructor; for(let key in obj){ newObj[key] = deepCopy(obj[key]) } return newObj;}