浅拷贝:拷贝的是地址
const obj = {
uname: "浩楠",
age: 22,
family: {
baby: "abc"
}
}
// 浅拷贝
const o = {};
Object.assign(o, obj);
o.age = 20;
console.log(o.age); // 20
console.log(obj.age); // 22
// 第二次属于复杂类型的则无法拷贝,因为只是吧第一层的具体值赋值给了新对象,复杂类型对象的值还是地址
o.family.baby = "aaa"
console.log(o.family.baby); // aaa
console.log(obj.family.baby); // aaa
浅拷贝,如果是单层对象可以,如果有多层则会出现问题
递归:与Java一直
模拟setInterval
function getTime(){
document.querySelector("div").innerHTML = new Date().toLocaleString();
setTimeout(getTime,1000);
}
getTime();
深拷贝
常见方法:
const obj = {
uname: 'pink',
age: 18,
hobby: ['乒乓球', '足球'],
family: {
baby: '小pink'
}
}
const o = {};
function deepCopy(newObj,oldObj){
for (let i in oldObj){
if(oldObj[i] instanceof Array){
newObj[i] = [];
deepCopy(newObj[i],oldObj[i]);
}else if(oldObj[i] instanceof Object){
newObj[i] = {};
deepCopy(newObj[i],oldObj[i]);
}else {
newObj[i] = oldObj[i];
}
}
}
deepCopy(o,obj);
// 修改值查看结果
o.age = 22;
console.log(o.age); // 22
console.log(obj.age); // 18
o.family.baby = "aaa";
console.log(obj.family.baby); // 小pink
const obj = {
uname: 'pink',
age: 18,
hobby: ['乒乓球', '足球'],
family: {
baby: '小pink'
}
}
const o = _.cloneDeep(obj);
console.log(o);
// 修改查看
o.family.baby = "aaa";
console.log(obj.family.baby); // 小pink
const obj = {
uname: 'pink',
age: 18,
hobby: ['乒乓球', '足球'],
family: {
baby: '小pink'
}
}
const o = JSON.parse(JSON.stringify(obj));
// 修改查看
obj.family.baby = "aaa";
console.log(o.family.baby); // 小pink
throw 抛出异常
function counter(x,y){
if(!x || !y){
// throw 参数不能为空
throw new Error("参数不能为空");
}
return x + y;
}
counter()
try / catch / finally
function fn(){
try{
// 可能错误的代码
document.querySelector(".p").style.color = "red";
}catch(error){
// 拦截错误,提示浏览器提供的错误信息,但不中断程序的执行
console.log(error.message);
// 抛出异常信息
throw new Error("选择器错误");
// 程序中断需要加return
// return
}finally{
// 总会执行的
console.log("一定会执行的代码");
}
console.log(1)
}
fn();
debugger
写在代码中,浏览器会自动定义到该代码前形成断点
函数.call()
语法
fun.call(this指向,参数1,参数2...);
返回值是函数的返回值,因为本意就是调用函数
const obj = {
name: "浩楠"
}
function fn(x,y){
console.log(this); // 没有改变this指向的时候为 window
console.log(x + y);
}
// call(调用this指向,arg1,arg2,..):改变指向并调用函数【返回值为函数结果返回值】
fn.call(obj,1,2);
apply()
fun.apply(this指向,[数组参数]);
const obj = {
name: "浩楠"
}
function fn(x,y){
console.log(this);
console.log(x + y);
}
// 函数.apply(this指向,数组参数):改变this指向并调用函数【返回值与call相同,不同在于参数传递为数组】
fn.apply(obj,[1,2]);
// 使用场景:求数组最大值
const arr = [100,44,77];
console.log("最大值:"+Math.max.apply(null,arr)); // 100
console.log("最小值:"+Math.min.apply(null,arr)); // 44
// 类似展开运算符
console.log(Math.max(...arr));
bind()
fun.bind(this指向,参数1,参数2..)
返回值由指定的this值和初始化参数改造的 原函数拷贝
当指向改变this指向,并不想调用的时候,使用 bind,比如改变定时器内部的this指向
const obj = {
name: "浩楠"
}
function fn(){
console.log(this);
}
// 函数.bind(this指向):改变this指向,不会调用函数【返回值是更改过this指向的函数】
const fun = fn.bind(obj);
fun();
// 需求:按钮点击就禁用,两秒后开启
document.querySelector("button").addEventListener("click",function(){
// 禁用
this.disabled = true;
window.setTimeout(function(){
// 要将指向window的this改为 按钮
this.disabled = false;
}.bind(this),2000)
})
总结三个方法
防抖
// 利用防抖实现性能优化
const box = document.querySelector(".box");
let i = 0;
function mouseMove(){
box.innerHTML = i++;
}
// box.addEventListener("mousemove",mouseMove);
// 500秒后 +1:利用lodash库
// box.addEventListener("mousemove",_.debounce(mouseMove,500));
// 手写防抖函数
function debounce(fun,time){
let timerId;
return function(){
if(timerId){
clearTimeout(timerId);
}
timerId = setTimeout(fun,time)
}
}
box.addEventListener("mousemove",debounce(mouseMove,500));
节流
// 利用节流实现性能优化
const box = document.querySelector(".box");
let i = 0;
function mouseMove(){
box.innerHTML = i++;
}
// box.addEventListener("mousemove",mouseMove);
// 500秒后 +1:利用lodash库
// box.addEventListener("mousemove",_.throttle(mouseMove,3000));
// 手写节流函数
function throttle(fun,time){
let timerId = null
return function(){
if(!timerId){
timerId = setTimeout(function(){
fun();
timerId = null
},time)
}
}
}
box.addEventListener("mousemove",throttle(mouseMove,2000));
<body>
<div class="container">
<div class="header">
<a href="http://pip.itcast.cn">
<img src="https://pip.itcast.cn/img/logo_v3.29b9ba72.png" alt="" />
</a>
</div>
<div class="video">
<video src="https://v.itheima.net/LapADhV6.mp4" controls></video>
</div>
<div class="elevator">
<a href="javascript:;" data-ref="video">视频介绍</a>
<a href="javascript:;" data-ref="intro">课程简介</a>
<a href="javascript:;" data-ref="outline">评论列表</a>
</div>
</div>
<script src="./js/lodash.min.js"></script>
<script>
const video = document.querySelector("video");
video.ontimeupdate = _.throttle(() => {
// 获取当前视频时间 video.currentTime
localStorage.setItem("currentTime",video.currentTime);
console.log(video.currentTime);
},1000)
// 打开页面出发事件
video.onloadeddata = () => {
video.currentTime = localStorage.getItem("currentTime") || 0
}
</script>
</body>