深浅拷贝
浅拷贝
首先浅拷贝和深拷贝只针对引用类型
浅拷贝:拷贝的是地址
常见方法:
- 拷贝对象**:Object.assgin() **/ 展开运算符 {…obj} 拷贝对象
- 拷贝数组**:Array.prototype.concat() **或者 […arr]
<script>
const o = {
name:"小明",
age:20,
denger:"男",
famliy:{
mother:"小明妈妈"
}
}
// 方法一
// const red = {...o
// }
// console.log(o); // 下面的o.name更改的就是原来的对象;不影响red
// o.name = "red";
// console.log(red);
// 方法二
const red = {
}
Object.assign(red, o);
console.log(red);
red.name = "red"
red.famliy.mother = "red mother"
console.log(red);
console.log(o);
</script>
更改对象里面的方法属性会出现影响;所有对象的方法里的属性都改变了。
如果是简单数据类型拷贝值,**引用数据类型拷贝的是地址 **(简单理解: 如果是单层对象,没问题,如果有多层就有问题)
深拷贝
深拷贝:拷贝的是对象,不是地址
常见方法:
- 通过递归实现深拷贝
- lodash / cloneDeep
- 通过**JSON.stringify()**实现
- 通过递归实现深拷贝
- 函数递归:
如果一个函数在内部可以调用其本身,那么这个函数就是递归函数- 简单理解:函数内部自己调用自己, 这个函数就是递归函数
- 递归函数的作用和循环效果类似
- 由于递归很容易发生“栈溢出”错误(stack overflow),所以必须要加退出条件 return
- 函数递归:
let num = 1;
function fn() {
if (num >= 6) {
return document.write(num);
}
num++;
fn(); // 函数内部调用自己
}
fn()
** 利用递归函数实现 setTimeout 模拟 setInterval效果 **
利用递归函数实现 setTimeout 模拟 setInterval效果
需求:
①:页面每隔一秒输出当前的时间
②:输出当前时间可以使用:new Date().toLocaleString()
<body>
<h1></h1>
<script>
let h1 = document.querySelector("h1")
function getTime(){
const time = new Date().toLocaleString();
let str = time;
h1.innerHTML = time;
setTimeout(getTime, 1000);
}
getTime();
</script>
</body>
- js库 **lodash **里面 cloneDeep 内部实现了深拷贝
- js lodash库
- lodash.min.js
import { cloneDeep } from "lodash";
const o = {
uname: "username ",
age: 20,
hobby: ['篮球', '足球'],
famliy: {
baby: "baby"
}
}
// _.cloneDeep(要被克隆的对象)
const p = _.cloneDeep(o);
console.log(p);
p.famliy.baby = 'lao baby';
console.log(o);
- 通过JSON.stringify()实现
const obj ={
uname:"username",
age:20,
hobby: ['篮球', '足球'],
famliy: {
baby: "baby"
}
}
const o = JSON.parse(JSON.stringify(obj));
console.log(o);
o.famliy.baby ="lao baby";
console.log(obj);
异常处理
throw 抛异常
异常处理是指预估代码执行过程中可能发生的错误,然后最大程度的避免错误的发生导致整个程序无法继续运行
- throw 抛出异常信息,程序也会终止执行
- throw 后面跟的是错误提示信息
- Error 对象配合 throw 使用,能够设置更详细的错误信息
function counter(x,y){
if(!x || !y){
throw new Error("参数不能为空");
}
return x + y;
}
document.write(counter())
try /catch 捕获异常
我们可以通过** try / catch **捕获错误信息(浏览器提供的错误信息) try 试试 catch 拦住 finally 最后
- try…catch 用于捕获错误信息
- 将预估可能发生错误的代码写在 try 代码段中
- 如果 try 代码段中出现错误后,会执行 catch 代码段,并截获到错误信息4. finally 不管是否有错误,都会执行
function foo(){
try{
//查找DOM结点
const p = document.querySelector(".p");
p.style.color = "red";
}catch(error){
// try 代码段中执行有错误时,会执行catch代码段
// 查看错误信息
console.log(error.message);
console.log("出现问题");
// 终止代码
return
}finally{
alert("已执行")
}
console.log("如果出现错误,我的语句不会执行");
}
foo()
debugger
const arr = [1,3,5]
const newarr = arr.map((item, index) =>{
debugger
console.log(item);
console.log(index);
return item+10;
})
console.log(newarr);
处理this
this指向
this 是 JavaScript 最具“魅惑”的知识点,不同的应用场合 this 的取值可能会有意想不到的结果,在此我们对以往学习过的关于【 this 默认的取值】情况进行归纳和总结。
目标: 了解函数中 this 在不同场景下的默认值,知道动态指定函数 this 值的方法
普通函数的调用方式决定了 this 的值,即【谁调用 this 的值指向谁】
this指向-普通函数
- 目标: 能说出普通函数的this指向
- 普通函数的调用方式决定了 this 的值,即【谁调用 this 的值指向谁】
普通函数没有明确调用者时 this 值为 window,**严格模式下没有调用者时 this 的值为 undefined **
// 普通函数
function sayhi() {
console.log(this);
}
// 函数表达式
const sayhello = function(){
console.log(this);
}
// 函数的调用方式决定了 this 的值
sayhi(); // window
window.sayhi();
// 普通对象
const user = {
name:"小明",
walk:function(){
console.log(this);
}
}
// 动态为 user 添加方法
user.sayhi = sayhi;
user.sayHello = sayhello
// 函数调用方式,决定了 this 的值
user.sayhi
user.sayHello
this指向-箭头函数
- 目标: 能说出箭头函数的this指向
箭头函数中的 this 与普通函数完全不同,也不受调用方式的影响,事实上箭头函数中并不存在 this !
- 箭头函数会默认帮我们绑定外层 this 的值,所以在箭头函数中 this 的值和外层的 this 是一样的
- 箭头函数中的this引用的就是最近作用域中的this
- 向外层作用域中,一层一层查找this,直到有this的定义
console.log(this);// 此处指向window
const sayhi = function(){
console.log(this); // 该箭头函数中的 this 为函数声明环境中 this 一致
}
const user = {
name:"小明",
// 该箭头函数中的 this 为函数声明环境中 this 一致
walk:()=>{
console.log(this);
},
}
sayhi()
user.walk()
注意情况1:
在开发中【使用箭头函数前需要考虑函数中 this 的值】,事件回调函数使用箭头函数时,this 为全局的 window
因此DOM事件回调函数如果里面需要DOM对象的this,则不推荐使用箭头函数