快捷导航菜单
1、对象的深拷贝(一级属性拷贝和多级属性嵌套拷贝)
ES6的Object.assign函数,和{...xxx}扩展运算符能够实现浅拷贝。JSON.parse(JSON.stringify(xxx))能够实现深拷贝,但是针对要拷贝的属性值如果是函数、时间、undefined、正则表达式以及对象的原型属性和方法都无能为力。因此深拷贝需要自定义函数:
function deepClone(sourceObj){ if (sourceObj instanceof RegExp) return new RegExp(sourceObj); //正则类型 if (sourceObj instanceof Date) return new Date(sourceObj); //时间类型 if (sourceObj === null || typeof sourceObj !== 'object'){ //基础类型 return sourceObj; } //其他引用类型数据, 找出当前数据类型的构造函数,new一个当前类型的空对象 var obj = new sourceObj.constructor(); for (var key in sourceObj){ //属于自己的属性才递归深拷贝 if (sourceObj.hasOwnProperty(key)){ obj[key] = deepClone(sourceObj[key]); } } return obj; }
测试代码:
//测试 function Person(name, age){ this.name = name; this.age = age; } Person.prototype.myInfo = function(){ console.log("my name is ", this.name, ", age is ", this.age); } var obj = { fn: Person, //函数 obj: new Person("王大锤", 18), //对象 time: new Date("2018-08-18 18:18"), //时间 reg: new RegExp('abc'), //正则 sign: undefined, arr: ['etf', 99, true] } var obj2 = Object.assign({}, obj); //浅拷贝(ES6的Object.assign函数) var obj3 = {...obj}; //浅拷贝(ES6扩展运算符) //JSON.stringify深拷贝所有层级属性,但是针对属性值为函数,正则表达式,时间,undefined, 原型对象的方法和属性无能为力 var obj4 = JSON.parse(JSON.stringify(obj)); var obj5 = deepClone(obj); console.log("\n**************start*************") console.log("obj: ", obj, "\n\nobj2: ", obj2, "\n\nobj3: ", obj3, "\n\nobj4: \n", obj4, "\n\nobj5: ", obj5); obj.obj.name = '罗小虎', obj.obj.age = 27; obj.arr.push("玉娇龙"); console.log("............update.........") console.log("obj: ", obj, "\n\nobj2: ", obj2, "\n\nobj3: ", obj3, "\n\nobj4: \n", obj4, "\n\nobj5: ", obj5);
测试结果截图对比一下,发现使用JSON.stringify深拷贝的对象,属性值为函数和undefined的属性直接过滤不见了,然后正则表达式变成了空对象{}, 时间变成了字符串等:
2、网络图片转成base64, 在线图片或文件点击下载(隐藏链接)
<div>
<div onclick="clickMeDownload()">点我下载</div>
<script type="text/javascript">
/**
* 根据远程图片转成base64数据 (远程图片和当前页面不是同一域名时,需要进行web服务器配置,使其可以跨域下载)
* @param url 图片链接
* @param callback 回调函数
*/
function getBase64ByImgUrl(url, callback){
let canvas = document.createElement('canvas'),
ctx = canvas.getContext('2d'),
img = new Image;
img.crossOrigin = 'Anonymous';
img.onload = function(){
canvas.height = img.height;
canvas.width = img.width;
ctx.drawImage(img,0,0);
//获取base64数据
let base64 = canvas.toDataURL('image/png');
//回调
if (callback){
callback(base64);
}
canvas = null;
}
img.src = url;
}
/**
* 把base64转成文件流
* @param base64 base64数据
* @param filename 自定义文件的名字
*/
function getFileByBase64(base64, filename){
let arr = base64.split(','), mime = arr[0].match(/:(.*?);/)[1],
bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
while(n--){
u8arr[n] = bstr.charCodeAt(n);
}
return new File([u8arr], filename, {type:mime});
}
/**
* 测试例子:点击下载,隐藏下载链接
*/
function clickMeDownload(){
let imgUrl = 'https://img2018.cnblogs.com/blog/454511/201811/454511-20181114115022054-611805083.png';
getBase64ByImgUrl(imgUrl, function(base64){
console.log(base64);
//创建a标签, 设置a标签的href属性和download属性
var aEle = document.createElement('a');
aEle.setAttribute('href', base64);
aEle.setAttribute('download', 'temp.png');
aEle.style.display = 'none'; //隐藏a标签
document.body.appendChild(aEle); //将a标签添加到body里
aEle.click(); //触发a标签点击事件
document.body.removeChild(aEle); //下载图片后,移除a标签
});
}
</script>
</div>