对象拷贝(对象存在堆中)
变量直接赋值
赋值 就是一个=,比如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 是一个固定的属性,表示错误描述信息
}


















