对象拷贝(对象存在堆中)
变量直接赋值
赋值 就是一个=,比如let obj2=obj1 这就是赋值,只是把栈中存储的值,赋值给另一个变量
把obj1在栈中的地址,赋值给obj2
<script>
let str = 'hello'
let str2 = str //把str的值,赋值给str2.也就是str2='hello'
console.log(str2)
str = 'world' //修改str的值为world
console.log(str2) //hello
let obj1 = { name: 'zs', age: 20 }
let obj2 = obj1 //把obj1的值(obj1在存储在栈中的地址)赋值给obj2
console.log(obj2)
obj1.age = 1000
console.log(obj2)
</script>
浅拷贝
拷贝,就是把两个对象,完全的分开
目标:修改一个对象,另一个对象不受影响
<script>
let obj1 = { name: 'zs', age: 20 }
let obj2 = {} //写了这一行,表示obj1和obj2已将是两个不同的对象了
// 循环遍历obj1,循环一次,取obj1里面的一个属性,然后给obj2加上
for (let key in obj1) {
// key是变量 取键对应的键值为obj1[k]
obj2[key] = obj1[key]
}
obj1.name = 'lisi'
console.log(obj1)
console.log(obj2)
</script>
对象中还有引用类型值的情况,当对象中的对象发生改变,浅拷贝还是会发生改变(只拷贝了对象的第一层)
let obj1 = { name: 'zs', age: 20, msg: { xex: '男' } }
let obj2 = {} //写了这一行,表示obj1和obj2已将是两个不同的对象了
// 循环遍历obj1,循环一次,取obj1里面的一个属性,然后给obj2加上
for (let key in obj1) {
// key是变量 取键对应的键值为obj1[k]
obj2[key] = obj1[key]
}
// obj1的msg又是一个对象,里面保存的还是对象地址
obj1.msg.sex = '女'
console.log(obj1.msg.sex)
console.log(obj2.msg.sex)
递归
计算一个数的阶乘
<script>
// 计算一个数的阶乘
// 5的阶乘=5*4*3*2*1
// 写递归第一步,先找规律
// 规律:n的阶乘=n*(n-1)的阶乘
// 写递归的第二步:明确函数的功能
// 接下来。写一个函数,函数的功能是计算一个数的阶乘(当我需要计算一个数的阶乘的时候,就调用这个函数)
function fn(n)
{
// 如果n是1,则直接返回1
if(n===1) return 1
// return n的阶乘
// return n*(n-1)的阶乘 计算一个数的阶乘的时候就调用这个函数,则n-1的阶乘为fn(n-1)
return n*fn(n-1)
}
</script>
深拷贝
深拷贝,通过递归,逐层将对象的属性、属性值拷贝给另一个对象,使得两个对象能够完全分开
<script>
let obj1 = {
name: 'zs',
age: 20,
info: ['男', 180, 70],
dog: {
name: 'wangcai',
color: 'black',
child: {
name: '小旺财',
age: 2,
color: '花'
}
}
}
let obj2 = {}
// 前提:
// 1.准备好需要拷贝的对象、或者数组
// 2.准备好 一个空对象、或者空数组
// 拷贝的时候:
// 1.先判断拷贝的值是数组吗
// 2.在判断拷贝的值是对象吗
// 3.不是数组也不是对象,肯定是一个普通值,则直接拷贝
// 写一个函数,可以实现浅拷贝,当我需要浅拷贝的时候,直接调用这个函数即可
function fn(obj1, obj2) {
for (let key in obj1) {
// 循环的时候先判断,拷贝的值是数组还是对象
if (Array.isArray(obj1[key])) //obj1[key]是数组吗
{
obj2[key] = []
// 闲杂又需要obj1.info的值拷贝给obj2.info这个空数组,这又是一个浅拷贝,当我需要浅拷贝的时候,调用fn即可
fn(obj1[key], obj2[key])
}
else if (obj1 instanceof Object) //obj1如果有构造函数Object就是对象
{
obj2[key] = {}
fn(obj1[key], obj2[key])
}
else {
// 如果进入else,说明对象的值是普通的值,则直接浅拷贝
obj2[key] = obj1[key]
}
}
}
fn(obj1, obj2)
obj1.dog.name = 1234
console.log(obj1)
console.log(obj2)
</script>
小计
任何对象,原型链最顶层的对象对应的构造函数是Object
可以通过instance 判断该变量有没有构造函数Object来判断其是否是构造函数
其他拷贝方案
//上述使用for(let key in obj){}这样的语法实现的浅拷贝、深拷贝等等,讲解的主要目的是为了说明浅拷贝和深拷贝的概念
//实际工作中不会使用递归实现深拷贝
//其他拷贝方案:
//浅拷贝:(建议用)
Object.assign()------本意是实现对象的合并,但是可以用来实现浅拷贝
let obj=Object.assign({},obj1)
// 深拷贝(有缺陷,JSON中不能有函数,转成字符串时函数会丢失)(不建议用)
let obj1 = {
name: 'zs',
age: 20,
info: ['男', 180, 70],
dog: {
name: 'wangcai',
color: 'black',
child: {
name: '小旺财',
age: 2,
color: '花'
}
}
}
// 通过JSON.stringfy将上述对象先转为字符串
let obj2 = JSON.parse(JSON.stringify(obj1))
obj1.name = 'lisi'
obj1.dog.name = 1234
console.log(obj1)
console.log(obj2)
异常(知道语法就行)
throw抛出异常
<script>
function sum(x, y) {
if (x === undefined || y === undefined) {
// 如果符合这个条件,说明调用函数的时候,没有传递参数
// 实际使用,经常用throw和new Error()配合
// throw new Error('错误描述信息')
throw new Error('参数不对')
}
return x + y
}
console.log(sum())
</script>
try…catch语句
和if…else…差不多
try{
把你的代码全写到这里,
如果没有异常发生,则正常执行
如果有异常发生,则会把异常自动抛出
}catch(e){
e就是抛出的错误对象
e.message 是一个固定的属性,表示错误描述信息
}