共计 4815 个字符,预计需要花费 13 分钟才能阅读完成。
let 和 const
应用 var 带来的问题
var 净化全局变量
var a=1;
console.log(window.a)
var 会使变量晋升
console.log(a) // undefined
var 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、constructot
function 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=>s2
function 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;
}
正文完