浅拷贝,深拷贝
栈内存:简单数据类型Number String Boolean Null Undfined
堆内存:复杂数据类型Object Function Array
浅拷贝只复制指向某个对象的指针,而不复制对象本身,新旧对象还是共享同一块内存
深拷贝会另外创造一个一模一样的对象,新对象跟原对象不共享的,修改新对象不会改到原数组
直接赋值
举例:
//直接赋值 let arr1 = ["北京", "上海", "广州",["白云区","黄埔区"]] let arr2 = arr1; let arr2 = [] arr2[0] = "beijing" console.log("arr2", arr2) //["beijing", "上海", "广州",["白云区","黄埔区"]] console.log("arr1", arr1) //["beijing", "上海", "广州",["白云区","黄埔区"]]
直接赋值呢,使用的还是浅拷贝,数据存放的内存还是共享的
浅拷贝
举例:
let arr1 = ["北京", "上海", "广州",["白云区","黄埔区"]] let arr2 = arr1; //浅复制 for (var k in arr1) { arr2[k] = arr1[k] } arr2[0] = "beijing" arr2[3][0]="baiyunqu" // console.log("arr2", arr2) // console.log("arr1", arr1)
浅拷贝,修改arr1中的基本数据类型,存储的内存是不共享的,但是arr1里还有一个数组,要是修改深度的数组,内存还是共享的
深拷贝
举例:
let arr1 = ["北京", "上海", "广州",["白云区","黄埔区"]]for (k in arr1) { if (arr1[k] instanceof Array) { //数组 arr2[k] = [] for (var m in arr1[k]) { arr2[k][m] = arr1[k][m] } } else if (arr1[k] instanceof Object) { //对象 arr2[k] = {} for (n in arr1[k]) { arr2[k][n] = arr1[k][n] } } else { //字符串 arr2[k] = arr1[k] } } // arr2[3][0] = "baiyunqu" // console.log("arr2", arr2) // console.log("arr1", arr1) arr2[4].uname = "zhangsan" console.log("arr2", arr2) console.log("arr1", arr1)
深拷贝
深拷贝,就是通过if判断,判断里面的数据的类型,要是是Object和Array类型,就创建新的地址,然后把arr1中的内容赋值进去,(可以这么理解,就是重新创建了一个内存地址,让两者的内存地址不同,这样修改新对象,旧的数据也就不会变了),要是不是复杂数据类型,就是简单数据类型,直接赋值就好。
递归实现深拷贝
let arr1 = [ "北京", "上海", "广州", ["白云区", "黄埔区"], { uname: "张三", age: 21, school: { name: "李四", address: "北京" } } ] let arr2 = [] /*** * arr2 新数据 * arr1 旧数据 * **/ function deepCopy(arr2, arr1) { for (k in arr1) { if (arr1[k] instanceof Array) { //数组 arr2[k] = [] // for (var m in arr1[k]) { // arr2[k][m] = arr1[k][m] // } deepCopy(arr2[k], arr1[k]) } else if (arr1[k] instanceof Object) { //对象 arr2[k] = {} // for (n in arr1[k]) { // arr2[k][n] = arr1[k][n] // } deepCopy(arr2[k], arr1[k]) } else { //字符串 arr2[k] = arr1[k] } } } deepCopy(arr2, arr1) // arr2[4].uname = "zhangsan" arr2[4].school.name = "jiyunjiaoyu" console.log("arr2", arr2) console.log("arr1", arr1)
闭包
所谓的闭包呢,就是能够读取其他函数内部变量的函数
简单的来说呢,就是一个函数里面有变量,然后这个函数里面还有一个函数,而且这个函数还使用了外面函数的变量,这就是形成了所谓的闭包
举例:
/*闭包就是:能够读取其他函数内部变量的函数** */ function outer() { var num = 100; function inner() { num = 10 } inner() } outer()
暂时性死区
暂时性死区就是ES6中变量声明方法(let,const,class)声明的变量,不可以在声明之前进行调用,否则会进行显示报错。ES6变量声明前的代码区域,称为‘暂时性死区’
举例:
let x=1; let foo=function(){ //暂时性死区 console.log(x) let x=2; } foo()
模板字符串(超级字符串)
使用一对反引号包裹字符串,使用${}放置变量
优点:可以多行字符串换行书写,可以使用变量和表达式,不用用+拼接了
解构赋值
对象的解构赋值
取别名:
举例
//对象解构赋值 var obj = { uname: "张三", age: 21, sex: "男" } // var uname = obj.uname; // var age = obj.age; // var sex = obj.sex //给变量起别名,用冒号 //以前的变量名自动失效 var { uname: xxx, age: yyy, sex } = obj
扩展运算符
举例:
var obj = { uname: "张三", age: 21, sex: "男" } //扩展运算符的使用 var { uname, ...age } = obj console.log(uname, age) //...扩展运算符就是把没有获取的属性名,放入一个自定义名称中(全部没有获取的属性名)
多层解构
举例:
//对象解构:多层解构 var obj = { uname: "张三", age: 21, shcool: { name: "李四", address: "北京" } } let { uname, age,shcool ,shcool: { name, address } } = obj //赋值的时候,拥有两个shcool,因为第一个shcool是对象格式的,第二个是scool里面的name,addredd属性的内容,不一样
在函数中使用
举例:
//形参里面的大括号,不是对象,是解构赋值 function demo({ uname, age }) { console.log(uname, age) } demo({ uname: "张三", age: 21 })
数组解构
var arr = ["北京", "上海", "广州", "深圳"] // var a = arr[0] // var b = arr[1] // var c = arr[2] // var d = arr[3] //顺序要对应准确 // var [xxx, yyy, c, d] = arr; //扩展运算符的使用 var [a, b, ...c] = arr console.log(a, b, c)
对象解构赋值和数组解构赋值的区别:
对象是通过属性名获取的,而数组呢是通过下标获取的,
对象的顺序可以随便,名字不能乱取 数据顺序要准确,名字随便