深拷贝、浅拷贝、赋值、数据类型、instanceof、typeof
- js的一般数据类型存储和引用类型的数据存储
数据类型
-
基本类型:string、boolean、number、null、undefined、symbol
typeof null —— object,其它都可以显示各自类型 -
引用类型:对象、数组、方法、Date、RegExp
typeof function —— function,其它 object -
instanceof
instanceof 运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上
object instanceof constructor object:某个实例对象 constructor:某个构造函数 用来检测 constructor.prototype 是否存在于参数 object 的原型链上。
浅拷贝与深拷贝的区别
-
浅拷贝:创建一个新对象,这个对象有着原始对象属性值的一份精确拷贝;如果属性是基本类型,拷贝的就是基本类型的值;如果属性是引用类型,拷贝的就是内存地址,所以如果其中一个对象改变了地址,就会影响到另一个
-
深拷贝:将一个对象从内存中完整的拷贝一份出来,从堆内存中开辟一个新的区域存放新对象,且修改新对象不会影响原对象
-
var obj = {} obj在栈里,{}在堆里
浅拷贝与赋值的区别
-
当我们把一个对象赋值给一个新的变量时,赋的其实时该对象在栈中的地址,而不是堆中的数据,也就是两个对象指向的时同一个存储空间,无论哪个发生改变,其实都是改变的存储空间的内容,因此两个对象是联动的(对象的所有类型都影响)
-
浅拷贝:重新在堆中创建内存,拷贝前后对象的基本数据类型互不影响,但拷贝前后对象的引用类型因共享同一块内存,会相互影响(浅拷贝的对象指向一个新的地址)(基本类型不影响,引用类型影响)
-
深拷贝:从堆内存中开辟一个新的区域存放新对象,对对象中的子对象进行递归拷贝,拷贝前后的两个对象互不影响(所有类型都不影响)
-
例子
var person = { name: 'xxx', hobby: ['1', '2', '3'] } var person1 = person person1.name = 'yyy' person1.hobby[0] = '11' console.log(person) console.log(person1) // 结果是一样的,都是修改过后的对象 // 这是赋值 function shallowCopy(obj){ var target = {} far(var i in obj) { if(obj.hasOwnProperty(i)) { target[i] = obj[i] } } return target } var person1 = shalloCopy(person) person1.name = 'yyy' person1.hobby[0] = '11' console.log(person) console.log(person1) // 结果不一样,基本类型不一样,引用类型一样
-
浅拷贝的实现:
-
Object.assign():var newObj = Object.assign({}, originObj)
-
lodash里面的_.clone
-
...展开运算符
-
Array.prototype.concat
-
Array.prototypo.slice
-
自行实现
function shallowCopy(obj){ var target = {} far(var i in obj) { if(obj.hasOwnProperty(i)) { target[i] = obj[i] } } return target }
深拷贝的实现:
-
JSON.parse(JSON.stringify())
弊端:无法拷贝Date、RegExp、function类型
-
递归的操作
function deepClone(obj) { var cloneObj = {} if (obj === null) return obj if (obj instanceof Date) return new Date(obj) if (obj instanceof RegExp) return new RegExp(obj) if (typeof obj !== 'object') return obj // 基本类型 far(var i in obj) { if(obj.hasOwnProperty(i)) { target[i] = deepClone(obj[i]) } } } -
Jquery.extend()
-
lodash里面的_.baseClone